[ooo-build-commit] 2 commits - patches/dev300 patches/mono

Kohei Yoshida kohei at kemper.freedesktop.org
Wed Sep 30 12:12:59 PDT 2009


 patches/dev300/apply                                |   29 
 patches/dev300/cws-kohei03-sc-m58.diff              | 3426 ++++++++++++++++++++
 patches/dev300/cws-kohei03-sc.diff                  |   79 
 patches/dev300/enable-sheet-protection-options.diff |   12 
 patches/mono/mono-testtools.diff                    |   19 
 5 files changed, 3492 insertions(+), 73 deletions(-)

New commits:
commit 3fdb4b323a0a593c1fe57c5d6fd8631ac1c2a0ab
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Wed Sep 30 15:10:46 2009 -0400

    Adjusted for dev300-m60.
    
    * patches/dev300/apply: excluded non-applying patches.
    
    * patches/dev300/enable-sheet-protection-options.diff: removed
      unnecessary hunk that was causing trouble agaist m60.
    
    * patches/mono/mono-testtools.diff: removed hunk that has
      already been applied.

diff --git a/patches/dev300/apply b/patches/dev300/apply
index f584225..f74039e 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -562,8 +562,11 @@ SectionIssue => i#29152
 # but has now been modified significantly, so the name of
 # this diff is a bit misleading.
 
-webdav-locking-from-ooo-build-2-4-1.diff
+[ WebDAV < dev300-m60 ]
+# FIXME: it doesn't apply against dev300-m60.
+# webdav-locking-from-ooo-build-2-4-1.diff
 
+[ WebDAV ]
 # fix saving files on Novell teaming via WebDaV
 webdav-locking-local-temp-file.diff, bnc#440514, kendy
 
@@ -647,6 +650,8 @@ calc-new-acceleration.diff, i#67029, michael
 
 sc-dp-gridlayout.diff, i#68544 n#190970, jody
 
+[ CalcFixes < dev300-m60 ]
+# TODO: These 3 patches no longer apply for dev300-m60.
 # Excel compatibility for handling of "string numbers".
 sc-string-arg.diff, i#5658, kohei
 
@@ -657,6 +662,7 @@ sc-string-arg-ref-formula-cell.diff, n#391330, kohei
 # Fix an error in presence of string literals in COUNTA.
 sc-string-arg-counta-fix.diff, n#446622, kohei
 
+[ CalcFixes ]
 # Print_Area/Print_Titles are only relevant for sheet local names, n#191005
 sc-xls-builtin-name-scope.diff, n#191005, n#257422, jonp
 
@@ -854,6 +860,17 @@ calc-selection-protected-cells.diff, n#542024, kohei
 calc-general-type-auto-decimal-sc.diff,      n#541973, kohei
 calc-general-type-auto-decimal-svtools.diff, n#541973, kohei
 
+[ CalcFixes >= dev300-m60 ]
+
+# Excel compatibility for handling of "string numbers".
+# LATER: I'll take care of this later. --kohei
+# sc-string-arg.diff, i#5658, kohei
+# Fix for the above string number patch, for cases where a formula cell is
+# being referenced by the origin cell.
+# sc-string-arg-ref-formula-cell.diff, n#391330, kohei
+# Fix an error in presence of string literals in COUNTA.
+# sc-string-arg-counta-fix.diff, n#446622, kohei
+
 # Support PHONETIC function to display asian phonetic guide.
 # LATER: I'll take care of this later.  --kohei
 # calc-formula-asian-phonetic.diff, i#80764, i#80765, i#80766, kohei
@@ -1151,9 +1168,12 @@ installer-get-path-correctly.diff, pmladek
 # allow to use the prebuilt jsr173_1.0_api.jar
 build-prebuilt-stax.diff, i#93116, pmladek
 
+[ BuildBits < dev300-m60 ]
 # fix build with neon-0.24
+# FIXME: this no longer applies against dev300-m60. 
 ucb-neon-0.24.diff, pmladek
 
+[ BuildBits ]
 # don't break dmake with environment variables containing space in the name
 # [which is a broken setup, but apparently most apps don't break with that ;-)] 
 dmake-space-in-envvar-name.diff, i#101786, jholesov
diff --git a/patches/dev300/enable-sheet-protection-options.diff b/patches/dev300/enable-sheet-protection-options.diff
index 5d14f75..148752f 100644
--- a/patches/dev300/enable-sheet-protection-options.diff
+++ b/patches/dev300/enable-sheet-protection-options.diff
@@ -9,14 +9,4 @@
  
  class ScDocument;
  class ScTableProtectionImpl;
---- sc/source/ui/docshell/docsh.cxx
-+++ sc/source/ui/docshell/docsh.cxx
-@@ -2011,7 +2011,7 @@
-             bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL);
-             if (bNeedRetypePassDlg && !pViewShell->ExecuteRetypePassDlg(PASSHASH_XL))
-             {
--                SetError( ERRCODE_ABORT );
-+                SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
-                 return false;
-             }
- #else
+
diff --git a/patches/mono/mono-testtools.diff b/patches/mono/mono-testtools.diff
index 5d78a1d..2a40bb2 100644
--- a/patches/mono/mono-testtools.diff
+++ b/patches/mono/mono-testtools.diff
@@ -85,25 +85,6 @@
  
 -.ENDIF
  
---- testtools/source/bridgetest/idl/makefile.mk.old	2009-04-02 11:05:37.000000000 +0000
-+++ testtools/source/bridgetest/idl/makefile.mk	2009-04-06 16:41:58.000000000 +0000
-@@ -51,6 +51,8 @@
-     - $(RM) $@
-     $(REGMERGE) $@ /UCR $(MISC)$/$(TARGET)$/bridgetest.urd
- 
-+.IF "$(GUI)" == "WNT"
-+.IF "$(COM)" != "GCC"
- 
- CLIMAKERFLAGS =
- .IF "$(debug)" != ""
-@@ -66,5 +68,7 @@
-         -X $(SOLARBINDIR)$/types.rdb $< 
-     $(TOUCH) $@
- 
-+.ENDIF
-+.ENDIF # GUI, WNT
- .ENDIF # L10N_framework
- 
 --- testtools/source/bridgetest/cli/cli_bridgetest_inprocess.cs.old	2009-04-02 11:05:37.000000000 +0000
 +++ testtools/source/bridgetest/cli/cli_bridgetest_inprocess.cs	2009-04-06 16:41:58.000000000 +0000
 @@ -130,26 +130,14 @@ public class BridgeTest
commit 1b9d48aadbba721c56623e35fa359df38f4dea44
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Wed Sep 30 14:43:48 2009 -0400

    Adjusted patch for dev300-m60.
    
    * patches/dev300/apply:
    * patches/dev300/cws-kohei03-sc-m58.diff:
    * patches/dev300/cws-kohei03-sc.diff: re-generated from
      the cws after rebase.

diff --git a/patches/dev300/apply b/patches/dev300/apply
index 112fe8e..f584225 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -195,8 +195,11 @@ cws-koheicsvimport-sc.diff,        kohei
 # kohei03 cws
 cws-kohei03-chart2.diff, kohei
 
-[ CWSBackports >= dev300-m58 ]
-cws-kohei03-sc.diff,     kohei
+[ CWSBackports >= dev300-m60 ]
+cws-kohei03-sc.diff, kohei
+
+[ CWSBackports >= dev300-m58 < dev300-m60 ]
+cws-kohei03-sc-m58.diff,     kohei
 
 [ CWSBackports < dev300-m58 ]
 cws-kohei03-sc-m57.diff, kohei
diff --git a/patches/dev300/cws-kohei03-sc-m58.diff b/patches/dev300/cws-kohei03-sc-m58.diff
new file mode 100644
index 0000000..bbd5526
--- /dev/null
+++ b/patches/dev300/cws-kohei03-sc-m58.diff
@@ -0,0 +1,3426 @@
+diff --git sc/inc/chart2uno.hxx sc/inc/chart2uno.hxx
+index 93afe64..46b7ff0 100644
+--- sc/inc/chart2uno.hxx
++++ sc/inc/chart2uno.hxx
+@@ -533,6 +533,14 @@ private:
+     };
+ 
+     ::std::list<Item>           m_aDataArray;
++
++    /** 
++     * Cached data for getData.  We may also need to cache data for the 
++     * numerical and textural data series if they turn out to be bottlenecks 
++     * under certain scenarios.
++     */ 
++    ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > m_aMixedDataCache;
++
+     ::com::sun::star::uno::Sequence<sal_Int32>  m_aHiddenValues;
+ 
+     // properties
+diff --git sc/inc/chartlis.hxx sc/inc/chartlis.hxx
+index a8a97d3..51ac644 100644
+--- sc/inc/chartlis.hxx
++++ sc/inc/chartlis.hxx
+@@ -49,7 +49,7 @@ class ScChartUnoData;
+ #include <com/sun/star/chart/XChartData.hpp>
+ #include <com/sun/star/chart/XChartDataChangeEventListener.hpp>
+ 
+-class ScChartListener : public StrData, public SvtListener
++class SC_DLLPUBLIC ScChartListener : public StrData, public SvtListener
+ {
+ public:
+     class ExternalRefListener : public ScExternalRefManager::LinkListener
+diff --git sc/inc/column.hxx sc/inc/column.hxx
+index e4c7ed4..983ca1f 100644
+--- sc/inc/column.hxx
++++ sc/inc/column.hxx
+@@ -114,7 +114,7 @@ private:
+ friend class ScDocument;					// fuer FillInfo
+ friend class ScDocumentIterator;
+ friend class ScValueIterator;
+-friend class ScQueryValueIterator;
++friend class ScDBQueryDataIterator;
+ friend class ScColumnIterator;
+ friend class ScQueryCellIterator;
+ friend class ScMarkedDataIter;
+diff --git sc/inc/datauno.hxx sc/inc/datauno.hxx
+index 3103875..44e0336 100644
+--- sc/inc/datauno.hxx
++++ sc/inc/datauno.hxx
+@@ -32,6 +32,8 @@
+ #define SC_DATAUNO_HXX
+ 
+ #include "global.hxx"
++#include "queryparam.hxx"
++
+ #include <svtools/itemprop.hxx>
+ #include <svtools/lstner.hxx>
+ #include <com/sun/star/sheet/TableFilterField.hpp>
+diff --git sc/inc/dociter.hxx sc/inc/dociter.hxx
+index d5d4235..350c611 100644
+--- sc/inc/dociter.hxx
++++ sc/inc/dociter.hxx
+@@ -35,6 +35,9 @@
+ #include <tools/solar.h>
+ #include "global.hxx"
+ #include "scdllapi.h"
++#include "queryparam.hxx"
++
++#include <memory>
+ 
+ class ScDocument;
+ class ScBaseCell;
+@@ -127,34 +130,91 @@ public:
+                     }
+ };
+ 
+-class ScQueryValueIterator            // alle Zahlenwerte in einem Bereich durchgehen
++// ============================================================================
++
++class ScDBQueryDataIterator
+ {
++public:
++    struct Value
++    {
++        ::rtl::OUString maString;
++        double          mfValue;
++        sal_uInt16      mnError;
++        bool            mbIsNumber;
++
++        Value();
++    };
++
+ private:
+-    ScQueryParam	aParam;
+-    ScDocument*		pDoc;
+-    const ScAttrArray*	pAttrArray;
+-    ULONG			nNumFormat;		// fuer CalcAsShown
+-    ULONG			nNumFmtIndex;
+-    SCCOL 			nCol;
+-    SCROW			nRow;
+-    SCSIZE			nColRow;
+-    SCROW			nAttrEndRow;
+-    SCTAB			nTab;
+-    short			nNumFmtType;
+-    BOOL			bCalcAsShown;
++    class DataAccess
++    {
++    public:
++        DataAccess(const ScDBQueryDataIterator* pParent);
++        virtual ~DataAccess() = 0;
++        virtual bool getCurrent(Value& rValue) = 0;
++        virtual bool getFirst(Value& rValue) = 0;
++        virtual bool getNext(Value& rValue) = 0;
++    protected:
++        const ScDBQueryDataIterator* mpParent;
++    };
++
++    class DataAccessInternal : public DataAccess
++    {
++    public:
++        DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc);
++        virtual ~DataAccessInternal();
++        virtual bool getCurrent(Value& rValue);
++        virtual bool getFirst(Value& rValue);
++        virtual bool getNext(Value& rValue);
++
++    private:
++        ScDBQueryParamInternal* mpParam;
++        ScDocument*         mpDoc;
++        const ScAttrArray*  pAttrArray;
++        ULONG               nNumFormat;     // for CalcAsShown
++        ULONG               nNumFmtIndex;
++        SCCOL               nCol;
++        SCROW               nRow;
++        SCSIZE              nColRow;
++        SCROW               nAttrEndRow;
++        SCTAB               nTab;
++        short               nNumFmtType;
++        bool                bCalcAsShown;
++    };
++
++    class DataAccessMatrix : public DataAccess
++    {
++    public:
++        DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam);
++        virtual ~DataAccessMatrix();
++        virtual bool getCurrent(Value& rValue);
++        virtual bool getFirst(Value& rValue);
++        virtual bool getNext(Value& rValue);
++
++    private:
++        bool isValidQuery(SCROW mnRow, const ScMatrix& rMat) const;
++
++        ScDBQueryParamMatrix* mpParam;
++        SCROW mnCurRow;
++        SCROW mnRows;
++        SCCOL mnCols;
++    };
++
++    ::std::auto_ptr<ScDBQueryParamBase> mpParam;
++    ::std::auto_ptr<DataAccess>         mpData;
++
++    bool            GetThis(Value& rValue);
+ 
+-    BOOL			GetThis(double& rValue, USHORT& rErr);
+ public:
+-                    ScQueryValueIterator(ScDocument* pDocument, SCTAB nTable,
+-                                         const ScQueryParam& aParam);
++                    ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam);
+     /// Does NOT reset rValue if no value found!
+-    BOOL			GetFirst(double& rValue, USHORT& rErr);
++    bool            GetFirst(Value& rValue);
+     /// Does NOT reset rValue if no value found!
+-    BOOL			GetNext(double& rValue, USHORT& rErr);
+-    void			GetCurNumFmtInfo( short& nType, ULONG& nIndex )
+-                        { nType = nNumFmtType; nIndex = nNumFmtIndex; }
++    bool            GetNext(Value& rValue);
+ };
+ 
++// ============================================================================
++
+ class ScCellIterator            // alle Zellen in einem Bereich durchgehen
+ {								// bei SubTotal aber keine ausgeblendeten und
+ private:						// SubTotalZeilen
+diff --git sc/inc/document.hxx sc/inc/document.hxx
+index 240765d..d01ee71 100644
+--- sc/inc/document.hxx
++++ sc/inc/document.hxx
+@@ -227,7 +227,7 @@ class ScDocument
+ {
+ friend class ScDocumentIterator;
+ friend class ScValueIterator;
+-friend class ScQueryValueIterator;
++friend class ScDBQueryDataIterator;
+ friend class ScCellIterator;
+ friend class ScQueryCellIterator;
+ friend class ScHorizontalCellIterator;
+diff --git sc/inc/dpcachetable.hxx sc/inc/dpcachetable.hxx
+index 7a60535..0a22fb0 100644
+--- sc/inc/dpcachetable.hxx
++++ sc/inc/dpcachetable.hxx
+@@ -60,6 +60,7 @@ class ScDPDimension;
+ class ScDPCollection;
+ struct ScDPCacheCell;
+ struct ScDPItemData;
++struct ScQueryParam;
+ class Date;
+ 
+ // ----------------------------------------------------------------------------
+diff --git sc/inc/dpshttab.hxx sc/inc/dpshttab.hxx
+index ede4933..8483ca2 100644
+--- sc/inc/dpshttab.hxx
++++ sc/inc/dpshttab.hxx
+@@ -35,6 +35,7 @@
+ #include "global.hxx"
+ #include "address.hxx"
+ #include "scdllapi.h"
++#include "queryparam.hxx"
+ 
+ #include <vector>
+ 
+diff --git sc/inc/global.hxx sc/inc/global.hxx
+index 57a6ff1..b401cb9 100644
+--- sc/inc/global.hxx
++++ sc/inc/global.hxx
+@@ -817,47 +817,6 @@ struct ScQueryEntry
+     BOOL			operator==( const ScQueryEntry& r ) const;
+ };
+ 
+-struct SC_DLLPUBLIC ScQueryParam
+-{
+-    SCCOL			nCol1;
+-    SCROW			nRow1;
+-    SCCOL			nCol2;
+-    SCROW			nRow2;
+-    SCTAB			nTab;
+-    BOOL			bHasHeader;
+-    BOOL			bByRow;
+-    BOOL			bInplace;
+-    BOOL			bCaseSens;
+-    BOOL			bRegExp;
+-    BOOL            bMixedComparison;   // whether numbers are smaller than strings
+-    BOOL			bDuplicate;
+-    BOOL			bDestPers;			// nicht gespeichert
+-    SCTAB			nDestTab;
+-    SCCOL			nDestCol;
+-    SCROW			nDestRow;
+-
+-private:
+-    SCSIZE			nEntryCount;
+-    ScQueryEntry*	pEntries;
+-
+-public:
+-    ScQueryParam();
+-    ScQueryParam( const ScQueryParam& r );
+-    ~ScQueryParam();
+-
+-    SCSIZE          GetEntryCount() const           { return nEntryCount; }
+-    ScQueryEntry&   GetEntry(SCSIZE n) const        { return pEntries[n]; }
+-    void            Resize(SCSIZE nNew);
+-
+-    ScQueryParam&   operator=   ( const ScQueryParam& r );
+-    BOOL            operator==  ( const ScQueryParam& rOther ) const;
+-    void            Clear       ();
+-    void            DeleteQuery( SCSIZE nPos );
+-
+-    void            MoveToDest();
+-    void            FillInExcelSyntax(String& aCellStr, SCSIZE nIndex);
+-};
+-
+ // -----------------------------------------------------------------------
+ 
+ struct SC_DLLPUBLIC ScSubTotalParam
+diff --git sc/inc/queryparam.hxx sc/inc/queryparam.hxx
+new file mode 100644
+index 0000000..bc50237
+--- /dev/null
++++ sc/inc/queryparam.hxx
+@@ -0,0 +1,142 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: interpre.hxx,v $
++ * $Revision: 1.35.44.2 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef SC_QUERYPARAM_HXX
++#define SC_QUERYPARAM_HXX
++
++#include "global.hxx"
++#include "scmatrix.hxx"
++
++#include <vector>
++
++struct ScDBQueryParamInternal;
++
++struct ScQueryParamBase
++{
++    bool            bHasHeader;
++    bool            bByRow;
++    bool            bInplace;
++    bool            bCaseSens;
++    bool            bRegExp;
++    bool            bDuplicate;
++    bool            bMixedComparison;   // whether numbers are smaller than strings
++
++    virtual ~ScQueryParamBase();
++
++    SC_DLLPUBLIC SCSIZE GetEntryCount() const;
++    SC_DLLPUBLIC ScQueryEntry& GetEntry(SCSIZE n) const;
++    void Resize(SCSIZE nNew);
++    SC_DLLPUBLIC void DeleteQuery( SCSIZE nPos );
++    void FillInExcelSyntax(String& aCellStr, SCSIZE nIndex);
++
++protected:
++    ScQueryParamBase();
++    ScQueryParamBase(const ScQueryParamBase& r);
++
++    mutable ::std::vector<ScQueryEntry>  maEntries;
++};
++
++// ============================================================================
++
++struct ScQueryParamTable
++{
++    SCCOL           nCol1;
++    SCROW           nRow1;
++    SCCOL           nCol2;
++    SCROW           nRow2;
++    SCTAB           nTab;
++
++    ScQueryParamTable();
++    ScQueryParamTable(const ScQueryParamTable& r);
++    virtual ~ScQueryParamTable();
++};
++
++// ============================================================================
++
++struct SC_DLLPUBLIC ScQueryParam : public ScQueryParamBase, public ScQueryParamTable
++{
++    BOOL            bDestPers;          // nicht gespeichert
++    SCTAB           nDestTab;
++    SCCOL           nDestCol;
++    SCROW           nDestRow;
++
++    ScQueryParam();
++    ScQueryParam( const ScQueryParam& r );
++    ScQueryParam( const ScDBQueryParamInternal& r );
++    virtual ~ScQueryParam();
++
++    ScQueryParam&   operator=   ( const ScQueryParam& r );
++    BOOL            operator==  ( const ScQueryParam& rOther ) const;
++    void            Clear();
++    void            ClearDestParams();
++    void            MoveToDest();
++};
++
++// ============================================================================
++
++struct ScDBQueryParamBase : public ScQueryParamBase
++{
++    enum DataType { INTERNAL, MATRIX };
++
++    SCCOL   mnField;    /// the field in which the values are processed during iteration.
++    bool    mbSkipString;
++
++    DataType        GetType() const;
++
++    virtual ~ScDBQueryParamBase();
++
++protected:
++    ScDBQueryParamBase(DataType eType);
++
++private:
++    ScDBQueryParamBase();
++
++    DataType        meType;
++};
++
++// ============================================================================
++
++struct ScDBQueryParamInternal : public ScDBQueryParamBase, public ScQueryParamTable
++{
++    ScDBQueryParamInternal();
++    virtual ~ScDBQueryParamInternal();
++};
++
++// ============================================================================
++
++struct ScDBQueryParamMatrix : public ScDBQueryParamBase
++{
++    ScMatrixRef mpMatrix;
++
++    ScDBQueryParamMatrix();
++    virtual ~ScDBQueryParamMatrix();
++};
++
++#endif
+diff --git sc/inc/reftokenhelper.hxx sc/inc/reftokenhelper.hxx
+index d7b335f..99a5998 100644
+--- sc/inc/reftokenhelper.hxx
++++ sc/inc/reftokenhelper.hxx
+@@ -70,12 +70,12 @@ public:
+ 
+     static void getTokensFromRangeList(::std::vector<ScSharedTokenRef>& pTokens, const ScRangeList& rRanges);
+ 
+-    static bool isRef(const ScSharedTokenRef& pToken);
+-    static bool isExternalRef(const ScSharedTokenRef& pToken);
++    static bool SC_DLLPUBLIC isRef(const ScSharedTokenRef& pToken);
++    static bool SC_DLLPUBLIC isExternalRef(const ScSharedTokenRef& pToken);
+ 
+-    static bool intersects(const ::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
++    static bool SC_DLLPUBLIC intersects(const ::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
+ 
+-    static void join(::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
++    static void SC_DLLPUBLIC join(::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
+ 
+     static bool getDoubleRefDataFromToken(ScComplexRefData& rData, const ScSharedTokenRef& pToken);
+ };
+diff --git sc/inc/table.hxx sc/inc/table.hxx
+index 8194e25..589d73f 100644
+--- sc/inc/table.hxx
++++ sc/inc/table.hxx
+@@ -161,7 +161,7 @@ private:
+ friend class ScDocument;					// fuer FillInfo
+ friend class ScDocumentIterator;
+ friend class ScValueIterator;
+-friend class ScQueryValueIterator;
++friend class ScDBQueryDataIterator;
+ friend class ScCellIterator;
+ friend class ScQueryCellIterator;
+ friend class ScHorizontalCellIterator;
+diff --git sc/source/core/data/autonamecache.cxx sc/source/core/data/autonamecache.cxx
+index ea41e3e..329e7f4 100644
+--- sc/source/core/data/autonamecache.cxx
++++ sc/source/core/data/autonamecache.cxx
+@@ -40,6 +40,7 @@
+ #include "autonamecache.hxx"
+ #include "dociter.hxx"
+ #include "cell.hxx"
++#include "queryparam.hxx"
+ 
+ // -----------------------------------------------------------------------
+ 
+diff --git sc/source/core/data/cell.cxx sc/source/core/data/cell.cxx
+index 2ae9972..09da3d6 100644
+--- sc/source/core/data/cell.cxx
++++ sc/source/core/data/cell.cxx
+@@ -1851,8 +1851,7 @@ void ScFormulaCell::SetDirty()
+ 
+ void ScFormulaCell::SetDirtyAfterLoad()
+ {
+-    bDirty = TRUE;
+-    if ( !pDocument->GetHardRecalcState() )
++    if ( bDirty && !pDocument->GetHardRecalcState() )
+         pDocument->PutInFormulaTree( this );
+ }
+ 
+diff --git sc/source/core/data/dociter.cxx sc/source/core/data/dociter.cxx
+index f7f836e..031b70a 100644
+--- sc/source/core/data/dociter.cxx
++++ sc/source/core/data/dociter.cxx
+@@ -47,9 +47,23 @@
+ #include "docoptio.hxx"
+ #include "cellform.hxx"
+ 
++#include <vector>
++
++using ::rtl::math::approxEqual;
++using ::std::vector;
++using ::rtl::OUString;
+ 
+ // STATIC DATA -----------------------------------------------------------
+ 
++namespace {
++
++void lcl_toUpper(OUString& rStr)
++{
++    rStr = ScGlobal::pCharClass->toUpper(rStr.trim(), 0, rStr.getLength());
++}
++
++}
++
+ ScDocumentIterator::ScDocumentIterator( ScDocument* pDocument,
+                             SCTAB nStartTable, SCTAB nEndTable ) :
+     pDoc( pDocument ),
+@@ -482,83 +496,85 @@ BOOL ScValueIterator::GetNext(double& rValue, USHORT& rErr)
+ }
+ */
+ 
+-//------------------------------------------------------------------------
+-//------------------------------------------------------------------------
++// ============================================================================
+ 
+-ScQueryValueIterator::ScQueryValueIterator(ScDocument* pDocument, SCTAB nTable, const ScQueryParam& rParam) :
+-    aParam (rParam),
+-    pDoc( pDocument ),
+-    nNumFmtIndex(0),
+-    nTab( nTable),
+-    nNumFmtType( NUMBERFORMAT_UNDEFINED ),
+-    bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() )
++ScDBQueryDataIterator::DataAccess::DataAccess(const ScDBQueryDataIterator* pParent) :
++    mpParent(pParent)
+ {
+-    nCol = aParam.nCol1;
+-    nRow = aParam.nRow1;
++}
++
++ScDBQueryDataIterator::DataAccess::~DataAccess()
++{
++}
++
++// ----------------------------------------------------------------------------
++
++ScDBQueryDataIterator::DataAccessInternal::DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc) :
++    DataAccess(pParent), 
++    mpParam(pParam),
++    mpDoc(pDoc)
++{
++    nCol = mpParam->mnField;
++    nRow = mpParam->nRow1;
++    nTab = mpParam->nTab;
++
+     nColRow = 0;					// wird bei GetFirst initialisiert
+     SCSIZE i;
+-    SCSIZE nCount = aParam.GetEntryCount();
+-    for (i=0; (i<nCount) && (aParam.GetEntry(i).bDoQuery); i++)
++	SCSIZE nCount = mpParam->GetEntryCount();
++	for (i=0; (i<nCount) && (mpParam->GetEntry(i).bDoQuery); i++)
+     {
+-        ScQueryEntry& rEntry = aParam.GetEntry(i);
++		ScQueryEntry& rEntry = mpParam->GetEntry(i);
+         sal_uInt32 nIndex = 0;
+         rEntry.bQueryByString =
+-                !(pDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
++				!(mpDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
+     }
+     nNumFormat = 0;					// werden bei GetNumberFormat initialisiert
+     pAttrArray = 0;
+     nAttrEndRow = 0;
+ }
+ 
+-BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
++ScDBQueryDataIterator::DataAccessInternal::~DataAccessInternal()
+ {
+-    ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+-    SCCOLROW nFirstQueryField = aParam.GetEntry(0).nField;
++}
++
++bool ScDBQueryDataIterator::DataAccessInternal::getCurrent(Value& rValue)
++{
++	ScColumn* pCol = &(mpDoc->pTab[nTab])->aCol[nCol];
++    SCCOLROW nFirstQueryField = mpParam->GetEntry(0).nField;
+     for ( ;; )
+     {
+-        if ( nRow > aParam.nRow2 )
++        if (nRow > mpParam->nRow2)
+         {
+-            nRow = aParam.nRow1;
+-            if (aParam.bHasHeader)
+-                nRow++;
+-            do
+-            {
+-                nCol++;
+-                if ( nCol > aParam.nCol2 )
+-                {
+-                    // rValue = 0.0;    // do not change caller's value!
+-                    rErr = 0;
+-                    return FALSE;				// Ende und Aus
+-                }
+-                pCol = &(pDoc->pTab[nTab])->aCol[nCol];
+-            } while ( pCol->nCount == 0 );
+-            pCol->Search( nRow, nColRow );
++            // Bottom of the range reached.  Bail out.
++            rValue.mnError = 0;
++            return false;
+         }
+ 
+         while ( (nColRow < pCol->nCount) && (pCol->pItems[nColRow].nRow < nRow) )
+             nColRow++;
+ 
+-        if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= aParam.nRow2 )
++		if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= mpParam->nRow2 )
+         {
+             nRow = pCol->pItems[nColRow].nRow;
+             ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
+-            if ( (pDoc->pTab[nTab])->ValidQuery( nRow, aParam, NULL,
++            if ( (mpDoc->pTab[nTab])->ValidQuery( nRow, *mpParam, NULL,
+                     (nCol == static_cast<SCCOL>(nFirstQueryField) ? pCell : NULL) ) )
+             {
+                 switch (pCell->GetCellType())
+                 {
+                     case CELLTYPE_VALUE:
+                         {
+-                            rValue = ((ScValueCell*)pCell)->GetValue();
++                            rValue.mfValue = ((ScValueCell*)pCell)->GetValue();
++                            rValue.mbIsNumber = true;
+                             if ( bCalcAsShown )
+                             {
+                                 lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
+-                                    nAttrEndRow, pCol->pAttrArray, nRow, pDoc );
+-                                rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
++									nAttrEndRow, pCol->pAttrArray, nRow, mpDoc );
++                                rValue.mfValue = mpDoc->RoundValueAsShown( rValue.mfValue, nNumFormat );
+                             }
+                             nNumFmtType = NUMBERFORMAT_NUMBER;
+                             nNumFmtIndex = 0;
+-                            rErr = 0;
++                            rValue.mnError = 0;
+                             return TRUE;		// gefunden
+                         }
+ //                        break;
+@@ -566,17 +582,31 @@ BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
+                         {
+                             if (((ScFormulaCell*)pCell)->IsValue())
+                             {
+-                                rValue = ((ScFormulaCell*)pCell)->GetValue();
+-                                pDoc->GetNumberFormatInfo( nNumFmtType,
++                                rValue.mfValue = ((ScFormulaCell*)pCell)->GetValue();
++                                rValue.mbIsNumber = true;
++                                mpDoc->GetNumberFormatInfo( nNumFmtType,
+                                     nNumFmtIndex, ScAddress( nCol, nRow, nTab ),
+                                     pCell );
+-                                rErr = ((ScFormulaCell*)pCell)->GetErrCode();
++                                rValue.mnError = ((ScFormulaCell*)pCell)->GetErrCode();
+                                 return TRUE;	// gefunden
+                             }
+                             else
+                                 nRow++;
+                         }
+                         break;
++                    case CELLTYPE_STRING:
++                    case CELLTYPE_EDIT:
++                        if (mpParam->mbSkipString)
++                            ++nRow;
++                        else
++                        {
++                            rValue.maString = pCell->GetStringData();
++                            rValue.mfValue = 0.0;
++                            rValue.mnError = 0;
++                            rValue.mbIsNumber = false;
++                            return true;
++                        }
++                        break;
+                     default:
+                         nRow++;
+                         break;
+@@ -586,30 +616,309 @@ BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
+                 nRow++;
+         }
+         else
+-            nRow = aParam.nRow2 + 1; // Naechste Spalte
++			nRow = mpParam->nRow2 + 1; // Naechste Spalte
+     }
+-//    return FALSE;
++    return false;
+ }
+ 
+-BOOL ScQueryValueIterator::GetFirst(double& rValue, USHORT& rErr)
++bool ScDBQueryDataIterator::DataAccessInternal::getFirst(Value& rValue)
+ {
+-    nCol = aParam.nCol1;
+-    nRow = aParam.nRow1;
+-    if (aParam.bHasHeader)
++    if (mpParam->bHasHeader)
+         nRow++;
+-//	nColRow = 0;
+-    ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
++//  nColRow = 0;
++    ScColumn* pCol = &(mpDoc->pTab[nTab])->aCol[nCol];
+     pCol->Search( nRow, nColRow );
+-    return GetThis(rValue, rErr);
++    return getCurrent(rValue);
+ }
+ 
+-BOOL ScQueryValueIterator::GetNext(double& rValue, USHORT& rErr)
++bool ScDBQueryDataIterator::DataAccessInternal::getNext(Value& rValue)
+ {
+     ++nRow;
+-    return GetThis(rValue, rErr);
++    return getCurrent(rValue);
+ }
+ 
+-//-------------------------------------------------------------------------------
++// ----------------------------------------------------------------------------
++
++ScDBQueryDataIterator::DataAccessMatrix::DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam) :
++    DataAccess(pParent),
++    mpParam(pParam)
++{
++    SCSIZE nC, nR;
++    mpParam->mpMatrix->GetDimensions(nC, nR);
++    mnRows = static_cast<SCROW>(nR);
++    mnCols = static_cast<SCCOL>(nC);
++}
++
++ScDBQueryDataIterator::DataAccessMatrix::~DataAccessMatrix()
++{
++}
++
++bool ScDBQueryDataIterator::DataAccessMatrix::getCurrent(Value& rValue)
++{
++    // Starting from row == mnCurRow, get the first row that satisfies all the
++    // query parameters.
++    for ( ;mnCurRow < mnRows; ++mnCurRow)
++    {
++        const ScMatrix& rMat = *mpParam->mpMatrix;
++        if (rMat.IsEmpty(mpParam->mnField, mnCurRow))
++            // Don't take empty values into account.
++            continue;
++
++        bool bIsStrVal = rMat.IsString(mpParam->mnField, mnCurRow);
++        if (bIsStrVal && mpParam->mbSkipString)
++            continue;
++
++        if (isValidQuery(mnCurRow, rMat))
++        {
++            rValue.maString = rMat.GetString(mpParam->mnField, mnCurRow);
++            rValue.mfValue = rMat.GetDouble(mpParam->mnField, mnCurRow);
++            rValue.mbIsNumber = !bIsStrVal;
++            rValue.mnError = 0;
++            return true;
++        }
++    }
++    return false;
++}
++
++bool ScDBQueryDataIterator::DataAccessMatrix::getFirst(Value& rValue)
++{
++    mnCurRow = mpParam->bHasHeader ? 1 : 0;
++    return getCurrent(rValue);
++}
++
++bool ScDBQueryDataIterator::DataAccessMatrix::getNext(Value& rValue)
++{
++    ++mnCurRow;
++    return getCurrent(rValue);
++}
++
++namespace {
++
++bool lcl_isQueryByValue(const ScQueryEntry& rEntry, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
++{
++    if (rEntry.bQueryByString)
++        return false;
++
++    if (!rMat.IsValueOrEmpty(nCol, nRow))
++        return false;
++
++    return true;
++}
++
++bool lcl_isQueryByString(const ScQueryEntry& rEntry, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
++{
++    switch (rEntry.eOp)
++    {
++        case SC_EQUAL:
++        case SC_NOT_EQUAL:
++        case SC_CONTAINS:
++        case SC_DOES_NOT_CONTAIN:
++        case SC_BEGINS_WITH:
++        case SC_ENDS_WITH:
++        case SC_DOES_NOT_BEGIN_WITH:
++        case SC_DOES_NOT_END_WITH:
++            return true;
++        default:
++            ;
++    }
++
++    if (rEntry.bQueryByString && rMat.IsString(nCol, nRow))
++        return true;
++
++    return false;
++}
++
++}
++
++bool ScDBQueryDataIterator::DataAccessMatrix::isValidQuery(SCROW nRow, const ScMatrix& rMat) const
++{
++    SCSIZE nEntryCount = mpParam->GetEntryCount();
++    vector<bool> aResults;
++    aResults.reserve(nEntryCount);
++
++    const CollatorWrapper& rCollator = 
++        mpParam->bCaseSens ? *ScGlobal::GetCaseCollator() : *ScGlobal::GetCollator();
++
++    for (SCSIZE i = 0; i < nEntryCount; ++i)
++    {
++        const ScQueryEntry& rEntry = mpParam->GetEntry(i);
++        if (!rEntry.bDoQuery)
++            continue;
++
++        switch (rEntry.eOp)
++        {
++            case SC_EQUAL:
++            case SC_LESS:
++            case SC_GREATER:
++            case SC_LESS_EQUAL:
++            case SC_GREATER_EQUAL:
++            case SC_NOT_EQUAL:
++                break;
++            default:
++                // Only the above operators are supported.
++                continue;
++        }
++
++        bool bValid = false;
++
++        SCSIZE nField = static_cast<SCSIZE>(rEntry.nField);
++        if (lcl_isQueryByValue(rEntry, rMat, nField, nRow))
++        {
++            // By value
++            double fMatVal = rMat.GetDouble(nField, nRow);
++            bool bEqual = approxEqual(fMatVal, rEntry.nVal);
++            switch (rEntry.eOp)
++            {
++                case SC_EQUAL:
++                    bValid = bEqual;
++                break;
++                case SC_LESS:
++                    bValid = (fMatVal < rEntry.nVal) && !bEqual;
++                break;
++                case SC_GREATER:
++                    bValid = (fMatVal > rEntry.nVal) && !bEqual;
++                break;
++                case SC_LESS_EQUAL:
++                    bValid = (fMatVal < rEntry.nVal) || bEqual;
++                break;
++                case SC_GREATER_EQUAL:
++                    bValid = (fMatVal > rEntry.nVal) || bEqual;
++                break;
++                case SC_NOT_EQUAL:
++                    bValid = !bEqual;
++                break;
++                default:
++                    ;
++            }
++        }
++        else if (lcl_isQueryByString(rEntry, rMat, nField, nRow))
++        {
++            // By string
++            do
++            {
++                if (!rEntry.pStr)
++                    break;
++
++                // Equality check first.
++
++                OUString aMatStr = rMat.GetString(nField, nRow);
++                lcl_toUpper(aMatStr);
++                OUString aQueryStr = *rEntry.pStr;
++                lcl_toUpper(aQueryStr);
++                bool bDone = false;
++                switch (rEntry.eOp)
++                {
++                    case SC_EQUAL:
++                        bValid = aMatStr.equals(aQueryStr);
++                        bDone = true;
++                    break;
++                    case SC_NOT_EQUAL:
++                        bValid = !aMatStr.equals(aQueryStr);
++                        bDone = true;
++                    break;
++                    default:
++                        ;
++                }
++
++                if (bDone)
++                    break;
++
++                // Unequality check using collator.
++
++                sal_Int32 nCompare = rCollator.compareString(aMatStr, aQueryStr);
++                switch (rEntry.eOp)
++                {
++                    case SC_LESS :
++                        bValid = (nCompare < 0);
++                    break;
++                    case SC_GREATER :
++                        bValid = (nCompare > 0);
++                    break;
++                    case SC_LESS_EQUAL :
++                        bValid = (nCompare <= 0);
++                    break;
++                    case SC_GREATER_EQUAL :
++                        bValid = (nCompare >= 0);
++                    break;
++                    default:
++                        ;
++                }
++            }
++            while (false);
++        }
++        else if (mpParam->bMixedComparison)
++        {
++            // Not used at the moment.
++        }
++
++        if (aResults.empty())
++            // First query entry.
++            aResults.push_back(bValid);
++        else if (rEntry.eConnect == SC_AND)
++        {
++            // For AND op, tuck the result into the last result value.
++            size_t n = aResults.size();    
++            aResults[n-1] = aResults[n-1] && bValid;
++        }
++        else
++            // For OR op, store its own result.
++            aResults.push_back(bValid);
++    }
++
++    // Row is valid as long as there is at least one result being true.
++    vector<bool>::const_iterator itr = aResults.begin(), itrEnd = aResults.end();
++    for (; itr != itrEnd; ++itr)
++        if (*itr)
++            return true;
++
++    return false;
++}
++
++// ----------------------------------------------------------------------------
++
++ScDBQueryDataIterator::Value::Value() :
++    mnError(0), mbIsNumber(true)
++{
++    ::rtl::math::setNan(&mfValue);
++}
++
++// ----------------------------------------------------------------------------
++
++ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam) :
++    mpParam (pParam)
++{
++    switch (mpParam->GetType())
++    {
++        case ScDBQueryParamBase::INTERNAL:
++        {
++            ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pParam);
++            mpData.reset(new DataAccessInternal(this, p, pDocument));
++        }
++        break;
++        case ScDBQueryParamBase::MATRIX:
++        {
++            ScDBQueryParamMatrix* p = static_cast<ScDBQueryParamMatrix*>(pParam);
++            mpData.reset(new DataAccessMatrix(this, p));
++        }
++    }
++}
++
++bool ScDBQueryDataIterator::GetThis(Value& rValue)
++{
++    return mpData->getCurrent(rValue);
++}
++
++bool ScDBQueryDataIterator::GetFirst(Value& rValue)
++{
++    return mpData->getFirst(rValue);
++}
++
++bool ScDBQueryDataIterator::GetNext(Value& rValue)
++{
++    return mpData->getNext(rValue);
++}
++
++// ============================================================================
+ 
+ ScCellIterator::ScCellIterator( ScDocument* pDocument,
+                                 SCCOL nSCol, SCROW nSRow, SCTAB nSTab,
+diff --git sc/source/core/data/dpcachetable.cxx sc/source/core/data/dpcachetable.cxx
+index 015c651..fd81c26 100644
+--- sc/source/core/data/dpcachetable.cxx
++++ sc/source/core/data/dpcachetable.cxx
+@@ -38,6 +38,7 @@
+ #include "dptabdat.hxx"
+ #include "dptabsrc.hxx"
+ #include "dpobject.hxx"
++#include "queryparam.hxx"
+ 
+ #include <com/sun/star/i18n/LocaleDataItem.hpp>
+ #include <com/sun/star/sdbc/DataType.hpp>
+diff --git sc/source/core/data/global2.cxx sc/source/core/data/global2.cxx
+index f71b842..181c634 100644
+--- sc/source/core/data/global2.cxx
++++ sc/source/core/data/global2.cxx
+@@ -243,238 +243,6 @@ utl::TextSearch* ScQueryEntry::GetSearchTextPtr( BOOL bCaseSens )
+ }
+ 
+ //------------------------------------------------------------------------
+-
+-ScQueryParam::ScQueryParam()
+-{
+-    nEntryCount = 0;
+-    Clear();
+-}
+-
+-//------------------------------------------------------------------------
+-
+-ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
+-        nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab),
+-        bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace), bCaseSens(r.bCaseSens),
+-        bRegExp(r.bRegExp), bMixedComparison(r.bMixedComparison),
+-        bDuplicate(r.bDuplicate), bDestPers(r.bDestPers),
+-        nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
+-{
+-    nEntryCount = 0;
+-
+-    Resize( r.nEntryCount );
+-    for (USHORT i=0; i<nEntryCount; i++)
+-        pEntries[i] = r.pEntries[i];
+-}
+-
+-//------------------------------------------------------------------------
+-
+-ScQueryParam::~ScQueryParam()
+-{
+-    delete[] pEntries;
+-}
+-
+-//------------------------------------------------------------------------
+-
+-void ScQueryParam::Clear()
+-{
+-    nCol1=nCol2=nDestCol = 0;
+-    nRow1=nRow2=nDestRow = 0;
+-    nDestTab = 0;
+-    nTab = SCTAB_MAX;
+-    bHasHeader = bCaseSens = bRegExp = bMixedComparison = FALSE;
+-    bInplace = bByRow = bDuplicate = bDestPers = TRUE;
+-
+-    Resize( MAXQUERY );
+-    for (USHORT i=0; i<MAXQUERY; i++)
+-        pEntries[i].Clear();
+-}
+-
+-//------------------------------------------------------------------------
+-
+-ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
+-{
+-    nCol1		= r.nCol1;
+-    nRow1		= r.nRow1;
+-    nCol2		= r.nCol2;
+-    nRow2		= r.nRow2;
+-    nTab		= r.nTab;
+-    nDestTab	= r.nDestTab;
+-    nDestCol	= r.nDestCol;
+-    nDestRow	= r.nDestRow;
+-    bHasHeader	= r.bHasHeader;
+-    bInplace	= r.bInplace;
+-    bCaseSens	= r.bCaseSens;
+-    bRegExp		= r.bRegExp;
+-    bMixedComparison = r.bMixedComparison;
+-    bDuplicate	= r.bDuplicate;
+-    bByRow		= r.bByRow;
+-    bDestPers	= r.bDestPers;
+-
+-    Resize( r.nEntryCount );
+-    for (USHORT i=0; i<nEntryCount; i++)
+-        pEntries[i] = r.pEntries[i];
+-
+-    return *this;
+-}
+-
+-//------------------------------------------------------------------------
+-
+-BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
+-{
+-    BOOL bEqual = FALSE;
+-
+-    // Anzahl der Queries gleich?
+-    USHORT nUsed 	  = 0;
+-    USHORT nOtherUsed = 0;
+-    while ( nUsed<nEntryCount && pEntries[nUsed].bDoQuery ) ++nUsed;
+-    while ( nOtherUsed<rOther.nEntryCount && rOther.pEntries[nOtherUsed].bDoQuery )
+-        ++nOtherUsed;
+-
+-    if (   (nUsed 		== nOtherUsed)
+-        && (nCol1		== rOther.nCol1)
+-        && (nRow1		== rOther.nRow1)
+-        && (nCol2		== rOther.nCol2)
+-        && (nRow2		== rOther.nRow2)
+-        && (nTab 		== rOther.nTab)
+-        && (bHasHeader	== rOther.bHasHeader)
+-        && (bByRow		== rOther.bByRow)
+-        && (bInplace	== rOther.bInplace)
+-        && (bCaseSens	== rOther.bCaseSens)
+-        && (bRegExp		== rOther.bRegExp)
+-        && (bMixedComparison == rOther.bMixedComparison)
+-        && (bDuplicate	== rOther.bDuplicate)
+-        && (bDestPers   == rOther.bDestPers)
+-        && (nDestTab	== rOther.nDestTab)
+-        && (nDestCol	== rOther.nDestCol)
+-        && (nDestRow	== rOther.nDestRow) )
+-    {
+-        bEqual = TRUE;
+-        for ( USHORT i=0; i<nUsed && bEqual; i++ )
+-            bEqual = pEntries[i] == rOther.pEntries[i];
+-    }
+-    return bEqual;
+-}
+-
+-//------------------------------------------------------------------------
+-
+-void ScQueryParam::DeleteQuery( SCSIZE nPos )
+-{
+-    if (nPos<nEntryCount)
+-    {
+-        for (SCSIZE i=nPos; i+1<nEntryCount; i++)
+-            pEntries[i] = pEntries[i+1];
+-
+-        pEntries[nEntryCount-1].Clear();
+-    }
+-    else
+-    {
+-        DBG_ERROR("Falscher Parameter bei ScQueryParam::DeleteQuery");
+-    }
+-}
+-
+-//------------------------------------------------------------------------
+-
+-void ScQueryParam::Resize(SCSIZE nNew)
+-{
+-    if ( nNew < MAXQUERY )
+-        nNew = MAXQUERY;				// nie weniger als MAXQUERY
+-
+-    ScQueryEntry* pNewEntries = NULL;
+-    if ( nNew )
+-        pNewEntries = new ScQueryEntry[nNew];
+-
+-    SCSIZE nCopy = Min( nEntryCount, nNew );
+-    for (SCSIZE i=0; i<nCopy; i++)
+-        pNewEntries[i] = pEntries[i];
+-
+-    if ( nEntryCount )
+-        delete[] pEntries;
+-    nEntryCount = nNew;
+-    pEntries = pNewEntries;
+-}
+-
+-//------------------------------------------------------------------------
+-
+-void ScQueryParam::MoveToDest()
+-{
+-    if (!bInplace)
+-    {
+-        SCsCOL nDifX = ((SCsCOL) nDestCol) - ((SCsCOL) nCol1);
+-        SCsROW nDifY = ((SCsROW) nDestRow) - ((SCsROW) nRow1);
+-        SCsTAB nDifZ = ((SCsTAB) nDestTab) - ((SCsTAB) nTab);
+-
+-        nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
+-        nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
+-        nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
+-        nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
+-        nTab  = sal::static_int_cast<SCTAB>( nTab  + nDifZ );
+-        for (USHORT i=0; i<nEntryCount; i++)
+-            pEntries[i].nField += nDifX;
+-
+-        bInplace = TRUE;
+-    }
+-    else
+-    {
+-        DBG_ERROR("MoveToDest, bInplace == TRUE");
+-    }
+-}
+-
+-//------------------------------------------------------------------------
+-
+-void ScQueryParam::FillInExcelSyntax(String& aCellStr, SCSIZE nIndex)
+-{
+-    if (aCellStr.Len() > 0)
+-    {
+-        if ( nIndex >= nEntryCount )
+-            Resize( nIndex+1 );
+-
+-        ScQueryEntry& rEntry = pEntries[nIndex];
+-
+-        rEntry.bDoQuery = TRUE;
+-        // Operatoren herausfiltern
+-        if (aCellStr.GetChar(0) == '<')
+-        {
+-            if (aCellStr.GetChar(1) == '>')
+-            {
+-                *rEntry.pStr = aCellStr.Copy(2);
+-                rEntry.eOp   = SC_NOT_EQUAL;
+-            }
+-            else if (aCellStr.GetChar(1) == '=')
+-            {
+-                *rEntry.pStr = aCellStr.Copy(2);
+-                rEntry.eOp   = SC_LESS_EQUAL;
+-            }
+-            else
+-            {
+-                *rEntry.pStr = aCellStr.Copy(1);
+-                rEntry.eOp   = SC_LESS;
+-            }
+-        }
+-        else if (aCellStr.GetChar(0) == '>')
+-        {
+-            if (aCellStr.GetChar(1) == '=')
+-            {
+-                *rEntry.pStr = aCellStr.Copy(2);
+-                rEntry.eOp   = SC_GREATER_EQUAL;
+-            }
+-            else
+-            {
+-                *rEntry.pStr = aCellStr.Copy(1);
+-                rEntry.eOp   = SC_GREATER;
+-            }
+-        }
+-        else
+-        {
+-            if (aCellStr.GetChar(0) == '=')
+-                *rEntry.pStr = aCellStr.Copy(1);
+-            else
+-                *rEntry.pStr = aCellStr;
+-            rEntry.eOp = SC_EQUAL;
+-        }
+-    }
+-}
+-
+-//------------------------------------------------------------------------
+ // struct ScSubTotalParam:
+ 
+ ScSubTotalParam::ScSubTotalParam()
+diff --git sc/source/core/data/sortparam.cxx sc/source/core/data/sortparam.cxx
+index 9531c71..dfab465 100644
+--- sc/source/core/data/sortparam.cxx
++++ sc/source/core/data/sortparam.cxx
+@@ -36,6 +36,7 @@
+ #include "sortparam.hxx"
+ #include "global.hxx"
+ #include "address.hxx"
++#include "queryparam.hxx"
+ #include <tools/debug.hxx>
+ 
+ 
+diff --git sc/source/core/data/table3.cxx sc/source/core/data/table3.cxx
+index ca196ea..2d8f0d3 100644
+--- sc/source/core/data/table3.cxx
++++ sc/source/core/data/table3.cxx
+@@ -60,6 +60,7 @@
+ #include "progress.hxx"
+ #include "cellform.hxx"
+ #include "postit.hxx"
++#include "queryparam.hxx"
+ 
+ #include <vector>
+ 
+diff --git sc/source/core/inc/doubleref.hxx sc/source/core/inc/doubleref.hxx
+new file mode 100644
+index 0000000..0aa577b
+--- /dev/null
++++ sc/source/core/inc/doubleref.hxx
+@@ -0,0 +1,194 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: interpre.hxx,v $
++ * $Revision: 1.35.44.2 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifndef SC_DOUBLEREF_HXX
++#define SC_DOUBLEREF_HXX
++
++#include "address.hxx"
++#include "scmatrix.hxx"
++
++class ScDocument;
++class ScBaseCell;
++class ScDBQueryParamBase;
++class ScQueryParamBase;
++
++// ============================================================================
++
++/** 
++ * Base class for abstracting range data backends for database functions. 
++ */
++class ScDBRangeBase
++{
++public:
++    enum RefType { INTERNAL, EXTERNAL };
++
++    virtual ~ScDBRangeBase() = 0;
++
++    RefType getType() const;
++    bool fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const;
++
++    virtual SCCOL getColSize() const = 0;
++    virtual SCROW getRowSize() const = 0;
++    virtual SCSIZE getVisibleDataCellCount() const = 0;
++
++    /** 
++     * Get a string value of a specified cell position.  Note that the 
++     * position of the upper left cell of the range is always (0, 0) even if 
++     * the reference type is of internal range.
++     *
++     * @param nCol column position (0 to column size-1)
++     * @param nRow row position (0 to row size-1)
++     */
++    virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const = 0;
++
++    virtual SCCOL getFirstFieldColumn() const = 0;
++
++    /** 
++     * Get a <i>0-based</i> column index that corresponds with the passed field
++     * index.  Note that the field index passed as the 1st parameter is 
++     * <i>1-based.</i> 
++     *
++     * @param nIndex 1-based field index.
++     * 
++     * @return 0-based column index
++     */
++    virtual SCCOL findFieldColumn(SCCOL nIndex) const = 0;
++    virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const = 0;
++    virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const = 0;
++    virtual bool isRangeEqual(const ScRange& rRange) const = 0;
++
++protected:
++    ScDBRangeBase(ScDocument* pDoc, RefType eType);
++    ScDocument* getDoc() const;
++
++    /** 
++     * Populate query options that are always the same for all database 
++     * queries.
++     */
++    static void fillQueryOptions(ScQueryParamBase* pParam);
++
++private:
++    ScDBRangeBase(); // disabled
++
++    ScDocument* mpDoc;
++    RefType meType;
++};
++
++// ============================================================================
++
++class ScDBInternalRange : public ScDBRangeBase
++{
++public:
++    explicit ScDBInternalRange(ScDocument* pDoc, const ScRange& rRange);
++    virtual ~ScDBInternalRange();
++
++    const ScRange& getRange() const;
++
++    virtual SCCOL getColSize() const;
++    virtual SCROW getRowSize() const;
++    virtual SCSIZE getVisibleDataCellCount() const;
++
++    /** 
++     * Get a string value of a specified cell position.  Note that the 
++     * position of the upper left cell of the range is always (0, 0) even if 
++     * the reference type is of internal range.
++     *
++     * @param nCol column position (0 to column size-1)
++     * @param nRow row position (0 to row size-1)
++     */
++    virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const;
++
++    virtual SCCOL getFirstFieldColumn() const;
++    /** 
++     * Get a <i>0-based</i> column index that corresponds with the passed field
++     * index.  Note that the field index passed as the 1st parameter is 
++     * <i>1-based.</i> 
++     *
++     * @param nIndex 1-based field index.
++     * 
++     * @return 0-based column index
++     */
++    virtual SCCOL findFieldColumn(SCCOL nIndex) const;
++    virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const;
++    virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const;
++    virtual bool isRangeEqual(const ScRange& rRange) const;
++
++private:
++    sal_uInt16 getCellString(::rtl::OUString& rStr, ScBaseCell* pCell) const;
++
++private:
++    ScRange maRange;
++};
++
++// ============================================================================
++
++class ScDBExternalRange : public ScDBRangeBase
++{
++public:
++    explicit ScDBExternalRange(ScDocument* pDoc, const ScMatrixRef& pMat);
++    virtual ~ScDBExternalRange();
++
++    virtual SCCOL getColSize() const;
++    virtual SCROW getRowSize() const;
++    virtual SCSIZE getVisibleDataCellCount() const;
++
++    /** 
++     * Get a string value of a specified cell position.  Note that the 
++     * position of the upper left cell of the range is always (0, 0) even if 
++     * the reference type is of internal range.
++     *
++     * @param nCol column position (0 to column size-1)
++     * @param nRow row position (0 to row size-1)
++     */
++    virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const;
++
++    virtual SCCOL getFirstFieldColumn() const;
++
++    /** 
++     * Get a <i>0-based</i> column index that corresponds with the passed field
++     * index.  Note that the field index passed as the 1st parameter is 
++     * <i>1-based.</i> 
++     *
++     * @param nIndex 1-based field index.
++     * 
++     * @return 0-based column index
++     */
++    virtual SCCOL findFieldColumn(SCCOL nIndex) const;
++    virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const;
++    virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const;
++    virtual bool isRangeEqual(const ScRange& rRange) const;
++
++private:
++    const ScMatrixRef mpMatrix;
++    SCCOL mnCols;
++    SCROW mnRows;
++};
++
++#endif
+diff --git sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
+index ca21e19..e385a9c 100644
+--- sc/source/core/inc/interpre.hxx
++++ sc/source/core/inc/interpre.hxx
+@@ -53,7 +53,10 @@ class SbxVariable;
+ class ScBaseCell;
+ class ScFormulaCell;
+ class SvNumberFormatter;
++class ScDBRangeBase;
+ struct MatrixDoubleOp;
++struct ScQueryParam;
++struct ScDBQueryParamBase;
+ 
+ struct ScCompare
+ {
+@@ -301,6 +304,7 @@ void DoubleRefToVars( const ScToken* p,
+         SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
+         SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
+         BOOL bDontCheckForTableOp = FALSE );
++ScDBRangeBase* PopDoubleRef();
+ void PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
+                           SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
+                           BOOL bDontCheckForTableOp = FALSE );
+@@ -488,7 +492,7 @@ void ScSubTotal();
+ // compatibility). If this was the case then rMissingField is set to TRUE upon
+ // return. If rMissingField==FALSE upon call all "missing cases" are considered
+ // to be an error.
+-BOOL GetDBParams( SCTAB& rTab, ScQueryParam& rParam, BOOL& rMissingField );
++ScDBQueryParamBase* GetDBParams( BOOL& rMissingField );
+ 
+ void DBIterator( ScIterFunc );
+ void ScDBSum();
+diff --git sc/source/core/tool/dbcolect.cxx sc/source/core/tool/dbcolect.cxx
+index e1e3870..a47a669 100644
+--- sc/source/core/tool/dbcolect.cxx
++++ sc/source/core/tool/dbcolect.cxx
+@@ -40,6 +40,7 @@
+ #include "refupdat.hxx"
+ #include "rechead.hxx"
+ #include "document.hxx"
++#include "queryparam.hxx"
+ #include "globstr.hrc"
+ 
+ 
+diff --git sc/source/core/tool/doubleref.cxx sc/source/core/tool/doubleref.cxx
+new file mode 100644
+index 0000000..bb67aad
+--- /dev/null
++++ sc/source/core/tool/doubleref.cxx
+@@ -0,0 +1,568 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: interpre.hxx,v $
++ * $Revision: 1.35.44.2 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_sc.hxx"
++
++// INCLUDE ---------------------------------------------------------------
++
++#include "doubleref.hxx"
++#include "cell.hxx"
++#include "global.hxx"
++#include "document.hxx"
++#include "queryparam.hxx"
++#include "globstr.hrc"
++
++#include <memory>
++#include <vector>
++
++using ::rtl::OUString;
++using ::std::auto_ptr;
++using ::std::vector;
++
++namespace {
++
++void lcl_toUpper(OUString& rStr)
++{
++    rStr = ScGlobal::pCharClass->toUpper(rStr.trim(), 0, rStr.getLength());
++}
++
++bool lcl_createStarQuery(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
++{
++    // A valid StarQuery must be at least 4 columns wide. To be precise it
++    // should be exactly 4 columns ...
++    // Additionally, if this wasn't checked, a formula pointing to a valid 1-3
++    // column Excel style query range immediately left to itself would result
++    // in a circular reference when the field name or operator or value (first
++    // to third query range column) is obtained (#i58354#). Furthermore, if the
++    // range wasn't sufficiently specified data changes wouldn't flag formula
++    // cells for recalculation.
++
++    if (pQueryRef->getColSize() < 4)
++        return false;
++
++    BOOL bValid;
++    BOOL bFound;
++    OUString aCellStr;
++    SCSIZE nIndex = 0;
++    SCROW nRow = 0;
++    SCROW nRows = pDBRef->getRowSize();
++    SCSIZE nNewEntries = static_cast<SCSIZE>(nRows);
++    pParam->Resize(nNewEntries);
++
++    do
++    {
++        ScQueryEntry& rEntry = pParam->GetEntry(nIndex);
++
++        bValid = FALSE;
++
++        if (nIndex > 0)
++        {
++            // For all entries after the first one, check the and/or connector in the first column.
++            aCellStr = pQueryRef->getString(0, nRow);
++            lcl_toUpper(aCellStr);
++            if ( aCellStr.equals(ScGlobal::GetRscString(STR_TABLE_UND)) )
++            {
++                rEntry.eConnect = SC_AND;
++                bValid = TRUE;
++            }
++            else if ( aCellStr.equals(ScGlobal::GetRscString(STR_TABLE_ODER)) )
++            {
++                rEntry.eConnect = SC_OR;
++                bValid = TRUE;
++            }
++        }
++
++        if ((nIndex < 1) || bValid)
++        {
++            // field name in the 2nd column.
++            bFound = FALSE;
++            aCellStr = pQueryRef->getString(1, nRow);
++            SCCOL nField = pDBRef->findFieldColumn(aCellStr); // TODO: must be case insensitive comparison.
++            if (ValidCol(nField))
++            {
++                rEntry.nField = nField;
++                bValid = true;
++            }
++            else
++                bValid = false;
++        }
++        
++        if (bValid)
++        {
++            // equality, non-equality operator in the 3rd column.
++            bFound = FALSE;
++            aCellStr = pQueryRef->getString(2, nRow);
++            lcl_toUpper(aCellStr);
++            const sal_Unicode* p = aCellStr.getStr();
++            if (p[0] == sal_Unicode('<'))
++            {
++                if (p[1] == sal_Unicode('>'))
++                    rEntry.eOp = SC_NOT_EQUAL;
++                else if (p[1] == sal_Unicode('='))
++                    rEntry.eOp = SC_LESS_EQUAL;
++                else
++                    rEntry.eOp = SC_LESS;
++            }
++            else if (p[0] == sal_Unicode('>'))
++            {
++                if (p[1] == sal_Unicode('='))
++                    rEntry.eOp = SC_GREATER_EQUAL;
++                else
++                    rEntry.eOp = SC_GREATER;
++            }
++            else if (p[0] == sal_Unicode('='))
++                rEntry.eOp = SC_EQUAL;
++
++        }
++        
++        if (bValid)
++        {
++            // Finally, the right-hand-side value in the 4th column.
++            *rEntry.pStr = pQueryRef->getString(3, nRow);
++            rEntry.bDoQuery = TRUE;
++        }
++        nIndex++;
++        nRow++;
++    }
++    while (bValid && (nRow < nRows) /* && (nIndex < MAXQUERY) */ );
++    return bValid;
++}
++
++bool lcl_createExcelQuery(
++    ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
++{
++    bool bValid = true;
++    SCCOL nCols = pQueryRef->getColSize();
++    SCROW nRows = pQueryRef->getRowSize();
++    vector<SCCOL> aFields(nCols);
++    SCCOL nCol = 0;
++    while (bValid && (nCol < nCols))
++    {
++        OUString aQueryStr = pQueryRef->getString(nCol, 0);
++        SCCOL nField = pDBRef->findFieldColumn(aQueryStr);
++        if (ValidCol(nField))
++            aFields[nCol] = nField;
++        else
++            bValid = false;
++        ++nCol;
++    }
++
++    if (bValid)
++    {
++//      ULONG nVisible = 0;
++//      for ( nCol=nCol1; nCol<=nCol2; nCol++ )
++//          nVisible += aCol[nCol].VisibleCount( nRow1+1, nRow2 );
++
++        // Count the number of visible cells (excluding the header row).  Each
++        // visible cell corresponds with a single query.
++        SCSIZE nVisible = pQueryRef->getVisibleDataCellCount();
++        if ( nVisible > SCSIZE_MAX / sizeof(void*) )
++        {
++            DBG_ERROR("zu viele Filterkritierien");
++            nVisible = 0;
++        }
++
++        SCSIZE nNewEntries = nVisible;
++        pParam->Resize( nNewEntries );
++
++        SCSIZE nIndex = 0;
++        SCROW nRow = 1;
++        String aCellStr;
++        while (nRow < nRows)
++        {
++            nCol = 0;
++            while (nCol < nCols)
++            {
++                aCellStr = pQueryRef->getString(nCol, nRow);
++                ScGlobal::pCharClass->toUpper( aCellStr );
++                if (aCellStr.Len() > 0)
++                {
++                    if (nIndex < nNewEntries)
++                    {
++                        pParam->GetEntry(nIndex).nField = aFields[nCol];
++                        pParam->FillInExcelSyntax(aCellStr, nIndex);
++                        nIndex++;
++                        if (nIndex < nNewEntries)
++                            pParam->GetEntry(nIndex).eConnect = SC_AND;
++                    }
++                    else
++                        bValid = FALSE;
++                }
++                nCol++;
++            }
++            nRow++;
++            if (nIndex < nNewEntries)
++                pParam->GetEntry(nIndex).eConnect = SC_OR;
++        }
++    }
++    return bValid;
++}
++
++bool lcl_fillQueryEntries(
++    ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
++{
++    SCSIZE nCount = pParam->GetEntryCount();
++    for (SCSIZE i = 0; i < nCount; ++i)
++        pParam->GetEntry(i).Clear();
++
++    // Standard QueryTabelle
++    bool bValid = lcl_createStarQuery(pParam, pDBRef, pQueryRef);
++    // Excel QueryTabelle
++    if (!bValid)
++        bValid = lcl_createExcelQuery(pParam, pDBRef, pQueryRef);
++
++    nCount = pParam->GetEntryCount();
++    if (bValid)
++    {
++        //  bQueryByString muss gesetzt sein
++        for (SCSIZE i = 0; i < nCount; ++i)
++            pParam->GetEntry(i).bQueryByString = true;
++    }
++    else
++    {
++        //  nix
++        for (SCSIZE i = 0; i < nCount; ++i)
++            pParam->GetEntry(i).Clear();
++    }
++    return bValid;
++}
++
++}
++
++// ============================================================================
++
++ScDBRangeBase::ScDBRangeBase(ScDocument* pDoc, RefType eType) : 
++    mpDoc(pDoc), meType(eType)
++{
++}
++
++ScDBRangeBase::~ScDBRangeBase()
++{
++}
++
++ScDBRangeBase::RefType ScDBRangeBase::getType() const
++{
++    return meType;
++}
++
++bool ScDBRangeBase::fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const
++{
++    if (!pDBRef)
++        return false;
++
++    return lcl_fillQueryEntries(pParam, pDBRef, this);
++}
++
++void ScDBRangeBase::fillQueryOptions(ScQueryParamBase* pParam)
++{
++    pParam->bHasHeader = true;
++    pParam->bByRow = true;
++    pParam->bInplace = true;
++    pParam->bCaseSens = false;
++    pParam->bRegExp = false;
++    pParam->bDuplicate = true;
++    pParam->bMixedComparison = false;
++}
++
++ScDocument* ScDBRangeBase::getDoc() const
++{
++    return mpDoc;
++}
++
++// ============================================================================
++
++ScDBInternalRange::ScDBInternalRange(ScDocument* pDoc, const ScRange& rRange) :
++    ScDBRangeBase(pDoc, INTERNAL), maRange(rRange)
++{
++}
++
++ScDBInternalRange::~ScDBInternalRange()
++{
++}
++
++const ScRange& ScDBInternalRange::getRange() const
++{
++    return maRange;
++}
++
++SCCOL ScDBInternalRange::getColSize() const
++{
++    return maRange.aEnd.Col() - maRange.aStart.Col() + 1;
++}
++
++SCROW ScDBInternalRange::getRowSize() const
++{
++    return maRange.aEnd.Row() - maRange.aStart.Row() + 1;
++}
++
++SCSIZE ScDBInternalRange::getVisibleDataCellCount() const
++{
++    SCCOL nCols = getColSize();
++    SCROW nRows = getRowSize();
++    if (nRows <= 1)
++        return 0;
++
++    return (nRows-1)*nCols;
++}
++
++OUString ScDBInternalRange::getString(SCCOL nCol, SCROW nRow) const
++{
++    String aStr;
++    const ScAddress& s = maRange.aStart;
++    getDoc()->GetString(s.Col() + nCol, s.Row() + nRow, maRange.aStart.Tab(), aStr);
++    return aStr;
++}
++
++SCCOL ScDBInternalRange::getFirstFieldColumn() const
++{
++    return getRange().aStart.Col();
++}
++
++SCCOL ScDBInternalRange::findFieldColumn(SCCOL nIndex) const
++{
++    const ScRange& rRange = getRange();
++    const ScAddress& s = rRange.aStart;
++    const ScAddress& e = rRange.aEnd;
++
++    SCCOL nDBCol1 = s.Col();
++    SCCOL nDBCol2 = e.Col();
++
++    if ( nIndex <= 0 || nIndex > (nDBCol2 - nDBCol1 + 1) )
++        return nDBCol1;
++
++    return Min(nDBCol2, static_cast<SCCOL>(nDBCol1 + nIndex - 1));
++}
++
++sal_uInt16 ScDBInternalRange::getCellString(OUString& rStr, ScBaseCell* pCell) const
++{
++    sal_uInt16 nErr = 0;
++    String aStr;
++    if (pCell)
++    {
++        SvNumberFormatter* pFormatter = getDoc()->GetFormatTable();
++        switch (pCell->GetCellType())
++        {
++            case CELLTYPE_STRING:
++                ((ScStringCell*) pCell)->GetString(aStr);
++            break;
++            case CELLTYPE_EDIT:
++                ((ScEditCell*) pCell)->GetString(aStr);
++            break;
++            case CELLTYPE_FORMULA:
++            {
++                ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
++                nErr = pFCell->GetErrCode();
++                if (pFCell->IsValue())
++                {
++                    double fVal = pFCell->GetValue();
++                    ULONG nIndex = pFormatter->GetStandardFormat(
++                                        NUMBERFORMAT_NUMBER,
++                                        ScGlobal::eLnge);
++                    pFormatter->GetInputLineString(fVal, nIndex, aStr);
++                }
++                else
++                    pFCell->GetString(aStr);
++            }
++            break;
++            case CELLTYPE_VALUE:
++            {
++                double fVal = ((ScValueCell*) pCell)->GetValue();
++                ULONG nIndex = pFormatter->GetStandardFormat(
++                                        NUMBERFORMAT_NUMBER,
++                                        ScGlobal::eLnge);
++                pFormatter->GetInputLineString(fVal, nIndex, aStr);
++            }
++            break;
++            default:
++                ;
++        }
++    }
++    rStr = aStr;
++    return nErr;
++}
++
++SCCOL ScDBInternalRange::findFieldColumn(const OUString& rStr, sal_uInt16* pErr) const
++{
++    const ScAddress& s = maRange.aStart;
++    const ScAddress& e = maRange.aEnd;
++    OUString aUpper = rStr;
++    lcl_toUpper(aUpper);
++
++    SCCOL nDBCol1 = s.Col();
++    SCROW nDBRow1 = s.Row();
++    SCTAB nDBTab1 = s.Tab();
++    SCCOL nDBCol2 = e.Col();
++
++    SCCOL   nField = nDBCol1;
++    BOOL    bFound = TRUE;
++
++    bFound = FALSE;
++    OUString aCellStr;
++    ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
++    while (!bFound && (aLook.Col() <= nDBCol2))
++    {
++        ScBaseCell* pCell = getDoc()->GetCell( aLook );
++        sal_uInt16 nErr = getCellString( aCellStr, pCell );
++        if (pErr)
++            *pErr = nErr;
++        lcl_toUpper(aCellStr);
++        bFound = ScGlobal::GetpTransliteration()->isEqual(aCellStr, aUpper);
++        if (!bFound)
++            aLook.IncCol();
++    }
++    nField = aLook.Col();
++
++    return bFound ? nField : -1;
++}
++
++ScDBQueryParamBase* ScDBInternalRange::createQueryParam(const ScDBRangeBase* pQueryRef) const
++{
++    auto_ptr<ScDBQueryParamInternal> pParam(new ScDBQueryParamInternal);
++
++    // Set the database range first.
++    const ScAddress& s = maRange.aStart;
++    const ScAddress& e = maRange.aEnd;
++    pParam->nCol1 = s.Col();
++    pParam->nRow1 = s.Row();
++    pParam->nCol2 = e.Col();
++    pParam->nRow2 = e.Row();
++    pParam->nTab  = s.Tab();
++
++    fillQueryOptions(pParam.get());
++
++    // Now construct the query entries from the query range.
++    if (!pQueryRef->fillQueryEntries(pParam.get(), this))
++        return NULL;
++
++    return pParam.release();
++}
++
++bool ScDBInternalRange::isRangeEqual(const ScRange& rRange) const
++{
++    return maRange == rRange;
++}
++
++// ============================================================================
++
++ScDBExternalRange::ScDBExternalRange(ScDocument* pDoc, const ScMatrixRef& pMat) :
++    ScDBRangeBase(pDoc, EXTERNAL), mpMatrix(pMat)
++{
++    SCSIZE nC, nR;
++    mpMatrix->GetDimensions(nC, nR);
++    mnCols = nC;
++    mnRows = nR;
++}
++
++ScDBExternalRange::~ScDBExternalRange()
++{
++}
++
++SCCOL ScDBExternalRange::getColSize() const
++{
++    return mnCols;
++}
++
++SCROW ScDBExternalRange::getRowSize() const
++{
++    return mnRows;
++}
++
++SCSIZE ScDBExternalRange::getVisibleDataCellCount() const
++{
++    SCCOL nCols = getColSize();
++    SCROW nRows = getRowSize();
++    if (nRows <= 1)
++        return 0;
++
++    return (nRows-1)*nCols;
++}
++
++OUString ScDBExternalRange::getString(SCCOL nCol, SCROW nRow) const
++{
++    if (nCol >= mnCols || nRow >= mnRows)
++        return OUString();
++
++    return mpMatrix->GetString(nCol, nRow);
++}
++
++SCCOL ScDBExternalRange::getFirstFieldColumn() const
++{
++    return 0;
++}
++
++SCCOL ScDBExternalRange::findFieldColumn(SCCOL nIndex) const
++{
++    if (nIndex < 1)
++        // 1st field
++        return 0;
++
++    if (nIndex > mnCols)
++        // last field
++        return mnCols - 1;
++
++    return nIndex - 1;
++}
++
++SCCOL ScDBExternalRange::findFieldColumn(const OUString& rStr, sal_uInt16* pErr) const
++{
++    if (pErr)
++        pErr = 0;
++
++    OUString aUpper = rStr;
++    lcl_toUpper(aUpper);
++    for (SCCOL i = 0; i < mnCols; ++i)
++    {
++        OUString aUpperVal = mpMatrix->GetString(i, 0);
++        lcl_toUpper(aUpperVal);
++        if (aUpper.equals(aUpperVal))
++            return i;
++    }
++    return -1;
++}
++
++ScDBQueryParamBase* ScDBExternalRange::createQueryParam(const ScDBRangeBase* pQueryRef) const
++{
++    auto_ptr<ScDBQueryParamMatrix> pParam(new ScDBQueryParamMatrix);
++    pParam->mpMatrix = mpMatrix;
++    fillQueryOptions(pParam.get());
++
++    // Now construct the query entries from the query range.
++    if (!pQueryRef->fillQueryEntries(pParam.get(), this))
++        return NULL;
++
++    return pParam.release();
++}
++
++bool ScDBExternalRange::isRangeEqual(const ScRange& /*rRange*/) const
++{
++    return false;
++}
++
+diff --git sc/source/core/tool/interpr1.cxx sc/source/core/tool/interpr1.cxx
+index 29a6884..eff5ea3 100644
+--- sc/source/core/tool/interpr1.cxx
++++ sc/source/core/tool/interpr1.cxx
+@@ -67,11 +67,14 @@
+ #include <string.h>
+ #include <math.h>
+ #include <vector>
++#include <memory>
+ #include "cellkeytranslator.hxx"
+ #include "lookupcache.hxx"
+ #include "rangenam.hxx"
+ #include "compiler.hxx"
+ #include "externalrefmgr.hxx"
++#include "doubleref.hxx"
++#include "queryparam.hxx"
+ 
+ #define SC_DOUBLE_MAXVALUE  1.7e307
+ 
+@@ -82,6 +85,8 @@ ScTokenStack* ScInterpreter::pGlobalStack = NULL;
+ BOOL ScInterpreter::bGlobalStackInUse = FALSE;
+ 
+ using namespace formula;
++using ::std::auto_ptr;
++
+ //-----------------------------------------------------------------------------
+ // Funktionen
+ //-----------------------------------------------------------------------------
+@@ -5619,11 +5624,9 @@ void ScInterpreter::ScSubTotal()
+ #endif
+ 
+ 
+-BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
+-        BOOL& rMissingField )
++ScDBQueryParamBase* ScInterpreter::GetDBParams( BOOL& rMissingField )
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::GetDBParams" );
+-    BOOL bRet = FALSE;
+     BOOL bAllowMissingField = FALSE;
+     if ( rMissingField )
+     {
+@@ -5632,14 +5635,10 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
+     }
+     if ( GetByte() == 3 )
+     {
+-
+-        SCCOL nQCol1;
+-        SCROW nQRow1;
+-        SCTAB nQTab1;
+-        SCCOL nQCol2;
+-        SCROW nQRow2;
+-        SCTAB nQTab2;
+-        PopDoubleRef(nQCol1, nQRow1, nQTab1, nQCol2, nQRow2, nQTab2);
++        // First, get the query criteria range.
++        ::std::auto_ptr<ScDBRangeBase> pQueryRef( PopDoubleRef() );
++        if (!pQueryRef.get())
++            return NULL;
+ 
+         BOOL    bByVal = TRUE;
+         double  nVal = 0.0;
+@@ -5695,116 +5694,85 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
+                 SetError( errIllegalParameter );
+         }
+ 
+-        SCCOL nDBCol1;
+-        SCROW nDBRow1;
+-        SCTAB nDBTab1;
+-        SCCOL nDBCol2;
+-        SCROW nDBRow2;
+-        SCTAB nDBTab2;
+-        PopDoubleRef(nDBCol1, nDBRow1, nDBTab1, nDBCol2, nDBRow2, nDBTab2);
++        auto_ptr<ScDBRangeBase> pDBRef( PopDoubleRef() );
+ 
+-        if ( nGlobalError == 0 && bRangeFake )
++        if (nGlobalError || !pDBRef.get())
++            return NULL;
++
++        if ( bRangeFake )
+         {
+             // range parameter must match entire database range
+-            if ( aMissingRange == ScRange( nDBCol1, nDBRow1, nDBTab1, nDBCol2,
+-                        nDBRow2, nDBTab2) )
++            if (pDBRef->isRangeEqual(aMissingRange))
+                 rMissingField = TRUE;
+             else
+                 SetError( errIllegalParameter );
+         }
+-        
+-        if (nGlobalError == 0)
++
++        if (nGlobalError)
++            return NULL;
++
++        SCCOL nField = pDBRef->getFirstFieldColumn();
++        if (rMissingField)
++            ; // special case
++        else if (bByVal)
++            nField = pDBRef->findFieldColumn(static_cast<SCCOL>(nVal));
++        else
+         {
+-            SCCOL   nField = nDBCol1;
+-            BOOL    bFound = TRUE;
++            sal_uInt16 nErr = 0;    
++            nField = pDBRef->findFieldColumn(aStr, &nErr);
++            SetError(nErr);
++        }
++
++        if (!ValidCol(nField))
++            return NULL;
++
++        auto_ptr<ScDBQueryParamBase> pParam( pDBRef->createQueryParam(pQueryRef.get()) );
++
++        if (pParam.get())
++        {
++            // An allowed missing field parameter sets the result field
++            // to any of the query fields, just to be able to return
++            // some cell from the iterator.        
+             if ( rMissingField )
+-                ;   // special case
+-            else if ( bByVal )
+-            {
+-                if ( nVal <= 0 || nVal > (nDBCol2 - nDBCol1 + 1) )
+-                    bFound = FALSE;
+-                else
+-                    nField = Min(nDBCol2, (SCCOL)(nDBCol1 + (SCCOL)nVal - 1));
+-            }
+-            else
++                nField = static_cast<SCCOL>(pParam->GetEntry(0).nField);
++            pParam->mnField = nField;
++
++            SCSIZE nCount = pParam->GetEntryCount();
++            for ( SCSIZE i=0; i < nCount; i++ )
+             {
+-                bFound = FALSE;
+-                String aCellStr;
+-                ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
+-                while (!bFound && (aLook.Col() <= nDBCol2))
+-                {
+-                    ScBaseCell* pCell = GetCell( aLook );
+-                    GetCellString( aCellStr, pCell );
+-                    bFound = ScGlobal::GetpTransliteration()->isEqual( aCellStr, aStr );
+-                    if (!bFound)
+-                        aLook.IncCol();
+-                }
+-                nField = aLook.Col();
+-            }
+-            if (bFound)
+-            {
+-                rParam.nCol1 = nDBCol1;
+-                rParam.nRow1 = nDBRow1;
+-                rParam.nCol2 = nDBCol2;
+-                rParam.nRow2 = nDBRow2;
+-                rParam.nTab  = nDBTab1;
+-                rParam.bHasHeader = TRUE;
+-                rParam.bByRow = TRUE;
+-                rParam.bInplace = TRUE;
+-                rParam.bCaseSens = FALSE;
+-                rParam.bRegExp = FALSE;
+-                rParam.bDuplicate = TRUE;
+-                if (pDok->CreateQueryParam(nQCol1, nQRow1, nQCol2, nQRow2, nQTab1, rParam))
+-                {
+-                    // An allowed missing field parameter sets the result field
+-                    // to any of the query fields, just to be able to return
+-                    // some cell from the iterator.
+-                    if ( rMissingField )
+-                        nField = static_cast<SCCOL>(rParam.GetEntry(0).nField);
+-
+-                    rParam.nCol1 = nField;
+-                    rParam.nCol2 = nField;
+-                    rTab = nDBTab1;
+-                    bRet = TRUE;
+-                    SCSIZE nCount = rParam.GetEntryCount();
+-                    for ( SCSIZE i=0; i < nCount; i++ )
+-                    {
+-                        ScQueryEntry& rEntry = rParam.GetEntry(i);
+-                        if ( rEntry.bDoQuery )
+-                        {
+-                            sal_uInt32 nIndex = 0;
+-                            rEntry.bQueryByString = !pFormatter->IsNumberFormat(
+-                                *rEntry.pStr, nIndex, rEntry.nVal );
+-                            if ( rEntry.bQueryByString && !rParam.bRegExp )
+-                                rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
+-                        }
+-                        else
+-                            break;  // for
+-                    }
++                ScQueryEntry& rEntry = pParam->GetEntry(i);
++                if ( rEntry.bDoQuery )
++                {
++                    sal_uInt32 nIndex = 0;
++                    rEntry.bQueryByString = !pFormatter->IsNumberFormat(
++                        *rEntry.pStr, nIndex, rEntry.nVal );
++                    if ( rEntry.bQueryByString && !pParam->bRegExp )
++                        pParam->bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
+                 }
++                else
++                    break;  // for
+             }
++            return pParam.release();
+         }
+     }
+-    return bRet;
++    return false;
+ }
+ 
+ 
+ void ScInterpreter::DBIterator( ScIterFunc eFunc )
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::DBIterator" );
+-    SCTAB nTab1;
+     double nErg = 0.0;
+     double fMem = 0.0;
+     BOOL bNull = TRUE;
+     ULONG nCount = 0;
+-    ScQueryParam aQueryParam;
+     BOOL bMissingField = FALSE;
+-    if ( GetDBParams( nTab1, aQueryParam, bMissingField) )
++    auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
++    if (pQueryParam.get())
+     {
+-        double nVal;
+-        USHORT nErr;
+-        ScQueryValueIterator aValIter(pDok, nTab1, aQueryParam);
+-        if ( aValIter.GetFirst(nVal, nErr) && !nErr )
++        ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
++        ScDBQueryDataIterator::Value aValue;
++        if ( aValIter.GetFirst(aValue) && !aValue.mnError )
+         {
+             switch( eFunc )
+             {
+@@ -5820,24 +5788,24 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc )
+                 {
+                     case ifAVERAGE:
+                     case ifSUM:
+-                        if ( bNull && nVal != 0.0 )
++                        if ( bNull && aValue.mfValue != 0.0 )
+                         {
+                             bNull = FALSE;
+-                            fMem = nVal;
++                            fMem = aValue.mfValue;
+                         }
+                         else
+-                            nErg += nVal;
++                            nErg += aValue.mfValue;
+                         break;
+-                    case ifSUMSQ:   nErg += nVal * nVal; break;
+-                    case ifPRODUCT: nErg *= nVal; break;
+-                    case ifMAX:     if( nVal > nErg ) nErg = nVal; break;
+-                    case ifMIN:     if( nVal < nErg ) nErg = nVal; break;
++                    case ifSUMSQ:   nErg += aValue.mfValue * aValue.mfValue; break;
++                    case ifPRODUCT: nErg *= aValue.mfValue; break;
++                    case ifMAX:     if( aValue.mfValue > nErg ) nErg = aValue.mfValue; break;
++                    case ifMIN:     if( aValue.mfValue < nErg ) nErg = aValue.mfValue; break;
+                     default: ; // nothing
+                 }
+             }
+-            while ( aValIter.GetNext(nVal, nErr) && !nErr );
++            while ( aValIter.GetNext(aValue) && !aValue.mnError );
+         }
+-        SetError(nErr);
++        SetError(aValue.mnError);
+     }
+     else
+         SetError( errIllegalParameter);
+@@ -5862,13 +5830,12 @@ void ScInterpreter::ScDBSum()
+ void ScInterpreter::ScDBCount()
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScDBCount" );
+-    SCTAB nTab;
+-    ScQueryParam aQueryParam;
+     BOOL bMissingField = TRUE;
+-    if ( GetDBParams( nTab, aQueryParam, bMissingField) )
++    auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
++    if (pQueryParam.get())
+     {
+         ULONG nCount = 0;
+-        if ( bMissingField )
++        if ( bMissingField && pQueryParam->GetType() == ScDBQueryParamBase::INTERNAL )
+         {   // count all matching records
+             // TODO: currently the QueryIterators only return cell pointers of
+             // existing cells, so if a query matches an empty cell there's
+@@ -5878,7 +5845,9 @@ void ScInterpreter::ScDBCount()
+             // have to live with it until we reimplement the iterators to also
+             // return empty cells, which would mean to adapt all callers of
+             // iterators.
+-            ScQueryCellIterator aCellIter( pDok, nTab, aQueryParam);
++            ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pQueryParam.get());
++            SCTAB nTab = p->nTab;
++            ScQueryCellIterator aCellIter( pDok, nTab, *p);
+             if ( aCellIter.GetFirst() )
+             {
+                 do
+@@ -5889,17 +5858,17 @@ void ScInterpreter::ScDBCount()
+         }
+         else
+         {   // count only matching records with a value in the "result" field
+-            double nVal;
+-            USHORT nErr = 0;
+-            ScQueryValueIterator aValIter( pDok, nTab, aQueryParam);
+-            if ( aValIter.GetFirst( nVal, nErr) && !nErr )
++            ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
++            ScDBQueryDataIterator::Value aValue;
++            if ( aValIter.GetFirst(aValue) && !aValue.mnError )
+             {
+                 do
+                 {
+                     nCount++;
+-                } while ( aValIter.GetNext( nVal, nErr) && !nErr );
++                } 
++                while ( aValIter.GetNext(aValue) && !aValue.mnError );
+             }
+-            SetError( nErr );
++            SetError(aValue.mnError);
+         }
+         PushDouble( nCount );
+     }
+@@ -5911,21 +5880,24 @@ void ScInterpreter::ScDBCount()
+ void ScInterpreter::ScDBCount2()
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScDBCount2" );
+-    SCTAB nTab;
+-    ScQueryParam aQueryParam;
+     BOOL bMissingField = TRUE;
+-    if (GetDBParams( nTab, aQueryParam, bMissingField))
++    auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
++    if (pQueryParam.get())
+     {
+         ULONG nCount = 0;
+-        ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
+-        if ( aCellIter.GetFirst() )
++        pQueryParam->mbSkipString = false;
++        ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
++        ScDBQueryDataIterator::Value aValue;
++        if ( aValIter.GetFirst(aValue) && !aValue.mnError )
+         {
+             do
+             {
+                 nCount++;
+-            } while ( aCellIter.GetNext() );
++            } 
++            while ( aValIter.GetNext(aValue) && !aValue.mnError );
+         }
+-        PushDouble(nCount);
++        SetError(aValue.mnError);
++        PushDouble( nCount );
+     }
+     else
+         PushIllegalParameter();
+@@ -5969,25 +5941,23 @@ void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
+ 
+     rValCount = 0.0;
+     double fSum    = 0.0;
+-    SCTAB nTab;
+-    ScQueryParam aQueryParam;
+     BOOL bMissingField = FALSE;
+-    if (GetDBParams( nTab, aQueryParam, bMissingField))
++    auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
++    if (pQueryParam.get())
+     {
+-        double fVal;
+-        USHORT nErr;
+-        ScQueryValueIterator aValIter(pDok, nTab, aQueryParam);
+-        if (aValIter.GetFirst(fVal, nErr) && !nErr)
++        ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
++        ScDBQueryDataIterator::Value aValue;
++        if (aValIter.GetFirst(aValue) && !aValue.mnError)
+         {
+             do
+             {
+                 rValCount++;
+-                values.push_back(fVal);
+-                fSum += fVal;
++                values.push_back(aValue.mfValue);
++                fSum += aValue.mfValue;
+             }
+-            while ((nErr == 0) && aValIter.GetNext(fVal, nErr));
++            while ((aValue.mnError == 0) && aValIter.GetNext(aValue));
+         }
+-        SetError(nErr);
++        SetError(aValue.mnError);
+     }
+     else
+         SetError( errIllegalParameter);
+diff --git sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
+index cf8dc7e..a301200 100644
+--- sc/source/core/tool/interpr4.cxx
++++ sc/source/core/tool/interpr4.cxx
+@@ -68,15 +68,18 @@
+ #include "jumpmatrix.hxx"
+ #include "parclass.hxx"
+ #include "externalrefmgr.hxx"
++#include "doubleref.hxx"
+ 
+ #include <math.h>
+ #include <float.h>
+ #include <map>
+ #include <algorithm>
+ #include <functional>
++#include <memory>
+ 
+ using namespace com::sun::star;
+ using namespace formula;
++using ::std::auto_ptr;
+ 
+ #define ADDIN_MAXSTRLEN 256
+ 
+@@ -1021,6 +1024,44 @@ void ScInterpreter::DoubleRefToVars( const ScToken* p,
+     }
+ }
+ 
++ScDBRangeBase* ScInterpreter::PopDoubleRef()
++{
++    if (!sp)
++    {    
++        SetError(errUnknownStackVariable);
++        return NULL;
++    }
++
++    --sp;
++    FormulaToken* p = pStack[sp];
++    switch (p->GetType())
++    {
++        case svError:
++            nGlobalError = p->GetError();
++        break;
++        case svDoubleRef:
++        {
++            SCCOL nCol1, nCol2;
++            SCROW nRow1, nRow2;
++            SCTAB nTab1, nTab2;
++            DoubleRefToVars(static_cast<ScToken*>(p), 
++                            nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
++            
++            return new ScDBInternalRange(pDok,
++                ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
++        }
++        break;
++        case svMatrix:
++        {
++            ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
++            return new ScDBExternalRange(pDok, pMat);
++        }
++        break;
++        default:
++            SetError( errIllegalParameter);
++    }
++    return NULL;
++}
+ 
+ void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
+                                  SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
+@@ -1860,78 +1901,37 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
+ void ScInterpreter::ScDBGet()
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScDBGet" );
+-    SCTAB nTab;
+-    ScQueryParam aQueryParam;
+     BOOL bMissingField = FALSE;
+-    if (GetDBParams( nTab, aQueryParam, bMissingField))
++    auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
++    if (!pQueryParam.get())
+     {
+-        ScBaseCell* pCell;
+-        ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
+-        if ( (pCell = aCellIter.GetFirst()) != NULL )
+-        {
+-            if (aCellIter.GetNext())
+-                PushIllegalArgument();
+-            else
+-            {
+-                switch (pCell->GetCellType())
+-                {
+-                    case CELLTYPE_VALUE:
+-                    {
+-                        double rValue = ((ScValueCell*)pCell)->GetValue();
+-                        if ( bCalcAsShown )
+-                        {
+-                            ULONG nFormat;
+-                            nFormat = aCellIter.GetNumberFormat();
+-                            rValue = pDok->RoundValueAsShown( rValue, nFormat );
+-                        }
+-                        PushDouble(rValue);
+-                    }
+-                    break;
+-                    case CELLTYPE_STRING:
+-                    {
+-                        String rString;
+-                        ((ScStringCell*)pCell)->GetString(rString);
+-                        PushString(rString);
+-                    }
+-                    break;
+-                    case CELLTYPE_EDIT:
+-                    {
+-                        String rString;
+-                        ((ScEditCell*)pCell)->GetString(rString);
+-                        PushString(rString);
+-                    }
+-                    break;
+-                    case CELLTYPE_FORMULA:
+-                    {
+-                        USHORT rErr = ((ScFormulaCell*)pCell)->GetErrCode();
+-                        if (rErr)
+-                            PushError(rErr);
+-                        else if (((ScFormulaCell*)pCell)->IsValue())
+-                        {
+-                            double rValue = ((ScFormulaCell*)pCell)->GetValue();
+-                            PushDouble(rValue);
+-                        }
+-                        else
+-                        {
+-                            String rString;
+-                            ((ScFormulaCell*)pCell)->GetString(rString);
+-                            PushString(rString);
+-                        }
+-                    }
+-                    break;
+-                    case CELLTYPE_NONE:
+-                    case CELLTYPE_NOTE:
+-                    default:
+-                        PushIllegalArgument();
+-                    break;
+-                }
+-            }
+-        }
+-        else
+-            PushNoValue();
++        // Failed to create query param.
++        PushIllegalParameter();
++        return;
++    }
++
++    pQueryParam->mbSkipString = false;
++    ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
++    ScDBQueryDataIterator::Value aValue;
++    if (!aValIter.GetFirst(aValue) || aValue.mnError)
++    {
++        // No match found.
++        PushNoValue();
++        return;
++    }
++
++    ScDBQueryDataIterator::Value aValNext;
++    if (aValIter.GetNext(aValNext) && !aValNext.mnError)
++    {
++        // There should be only one unique match.
++        PushIllegalArgument();
++        return;
+     }
++
++    if (aValue.mbIsNumber)
++        PushDouble(aValue.mfValue);
+     else
+-        PushIllegalParameter();
++        PushString(aValue.maString);
+ }
+ 
+ 
+diff --git sc/source/core/tool/makefile.mk sc/source/core/tool/makefile.mk
+index b0f8f03..041d2c8 100644
+--- sc/source/core/tool/makefile.mk
++++ sc/source/core/tool/makefile.mk
+@@ -76,6 +76,7 @@ SLOFILES =  \
+         $(SLO)$/detdata.obj  \
+         $(SLO)$/detfunc.obj  \
+         $(SLO)$/docoptio.obj \
++		$(SLO)$/doubleref.obj \
+         $(SLO)$/editutil.obj \
+         $(SLO)$/filtopt.obj \
+         $(SLO)$/formulaparserpool.obj \
+@@ -95,6 +96,7 @@ SLOFILES =  \
+         $(SLO)$/printopt.obj \
+         $(SLO)$/prnsave.obj \
+         $(SLO)$/progress.obj \
++		$(SLO)$/queryparam.obj \
+         $(SLO)$/rangelst.obj \
+         $(SLO)$/rangenam.obj \
+         $(SLO)$/rangeseq.obj \
+@@ -123,6 +125,7 @@ EXCEPTIONSFILES= \
+         $(SLO)$/chartlock.obj \
+         $(SLO)$/chgtrack.obj \
+         $(SLO)$/compiler.obj \
++		$(SLO)$/doubleref.obj \
+         $(SLO)$/formulaparserpool.obj \
+         $(SLO)$/interpr1.obj \
+         $(SLO)$/interpr2.obj \
+@@ -131,6 +134,7 @@ EXCEPTIONSFILES= \
+         $(SLO)$/interpr5.obj \
+         $(SLO)$/lookupcache.obj \
+         $(SLO)$/prnsave.obj \
++		$(SLO)$/queryparam.obj \
+         $(SLO)$/reftokenhelper.obj \
+ 		$(SLO)$/stringutil.obj \
+         $(SLO)$/token.obj
+diff --git sc/source/core/tool/queryparam.cxx sc/source/core/tool/queryparam.cxx
+new file mode 100644
+index 0000000..d9d477d
+--- /dev/null
++++ sc/source/core/tool/queryparam.cxx
+@@ -0,0 +1,361 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ * 
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: interpr4.cxx,v $
++ * $Revision: 1.57.92.5 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++// MARKER(update_precomp.py): autogen include statement, do not remove
++#include "precompiled_sc.hxx"
++
++// INCLUDE ---------------------------------------------------------------
++
++#include "queryparam.hxx"
++
++using ::std::vector;
++
++// ============================================================================
++
++ScQueryParamBase::ScQueryParamBase()
++{
++    Resize( MAXQUERY );
++    for (USHORT i=0; i<MAXQUERY; i++)
++        maEntries[i].Clear();
++}
++
++ScQueryParamBase::ScQueryParamBase(const ScQueryParamBase& r) :
++    bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace), bCaseSens(r.bCaseSens),
++    bRegExp(r.bRegExp), bDuplicate(r.bDuplicate), bMixedComparison(r.bMixedComparison),
++    maEntries(r.maEntries)
++{
++}
++
++ScQueryParamBase::~ScQueryParamBase()
++{
++}
++
++SCSIZE ScQueryParamBase::GetEntryCount() const
++{
++    return maEntries.size();
++}
++
++ScQueryEntry& ScQueryParamBase::GetEntry(SCSIZE n) const
++{
++    return maEntries[n];
++}
++
++void ScQueryParamBase::Resize(SCSIZE nNew)
++{
++    if ( nNew < MAXQUERY )
++        nNew = MAXQUERY;                // nie weniger als MAXQUERY
++
++    vector<ScQueryEntry> aNewEntries(nNew);
++    SCSIZE nCopy = ::std::min(maEntries.size(), nNew);
++    for (SCSIZE i=0; i<nCopy; i++)
++        aNewEntries[i] = maEntries[i];
++
++    maEntries.swap(aNewEntries);
++}
++
++void ScQueryParamBase::DeleteQuery( SCSIZE nPos )
++{
++    if (nPos >= maEntries.size())
++        return;
++
++    size_t n = maEntries.size();
++    vector<ScQueryEntry> aNewEntries;
++    aNewEntries.reserve(n-1);
++    for (size_t i = 0; i < n; ++i)
++        if (i != nPos)
++            aNewEntries.push_back(maEntries[i]);
++
++    maEntries.swap(aNewEntries);
++}
++
++void ScQueryParamBase::FillInExcelSyntax(String& aCellStr, SCSIZE nIndex)
++{
++    if (aCellStr.Len() > 0)
++    {
++        if ( nIndex >= maEntries.size() )
++            Resize( nIndex+1 );
++
++        ScQueryEntry& rEntry = GetEntry(nIndex);
++
++        rEntry.bDoQuery = TRUE;
++        // Operatoren herausfiltern
++        if (aCellStr.GetChar(0) == '<')
++        {
++            if (aCellStr.GetChar(1) == '>')
++            {
++                *rEntry.pStr = aCellStr.Copy(2);
++                rEntry.eOp   = SC_NOT_EQUAL;
++            }
++            else if (aCellStr.GetChar(1) == '=')
++            {
++                *rEntry.pStr = aCellStr.Copy(2);
++                rEntry.eOp   = SC_LESS_EQUAL;
++            }
++            else
++            {
++                *rEntry.pStr = aCellStr.Copy(1);
++                rEntry.eOp   = SC_LESS;
++            }
++        }
++        else if (aCellStr.GetChar(0) == '>')
++        {
++            if (aCellStr.GetChar(1) == '=')
++            {
++                *rEntry.pStr = aCellStr.Copy(2);
++                rEntry.eOp   = SC_GREATER_EQUAL;
++            }
++            else
++            {
++                *rEntry.pStr = aCellStr.Copy(1);
++                rEntry.eOp   = SC_GREATER;
++            }
++        }
++        else
++        {
++            if (aCellStr.GetChar(0) == '=')
++                *rEntry.pStr = aCellStr.Copy(1);
++            else
++                *rEntry.pStr = aCellStr;
++            rEntry.eOp = SC_EQUAL;
++        }
++    }
++}
++
++// ============================================================================
++
++ScQueryParamTable::ScQueryParamTable()
++{
++}
++
++ScQueryParamTable::ScQueryParamTable(const ScQueryParamTable& r) :
++    nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab)
++{
++}
++
++ScQueryParamTable::~ScQueryParamTable()
++{
++}
++
++// ============================================================================
++
++ScQueryParam::ScQueryParam() : 
++    ScQueryParamBase(),
++    ScQueryParamTable()
++{
++    Clear();
++}
++
++//------------------------------------------------------------------------
++
++ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
++    ScQueryParamBase(r),
++    ScQueryParamTable(r),
++    bDestPers(r.bDestPers), nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
++{
++}
++
++ScQueryParam::ScQueryParam( const ScDBQueryParamInternal& r ) :
++    ScQueryParamBase(r),
++    ScQueryParamTable(r),
++    bDestPers(true),
++    nDestTab(0),
++    nDestCol(0),
++    nDestRow(0)
++{
++}
++    
++
++//------------------------------------------------------------------------
++
++ScQueryParam::~ScQueryParam()
++{
++}
++
++//------------------------------------------------------------------------
++
++void ScQueryParam::Clear()
++{
++    nCol1=nCol2 = 0;
++    nRow1=nRow2 = 0;
++    nTab = SCTAB_MAX;
++    bHasHeader = bCaseSens = bRegExp = bMixedComparison = FALSE;
++    bInplace = bByRow = bDuplicate = TRUE;
++
++    Resize( MAXQUERY );
++    for (USHORT i=0; i<MAXQUERY; i++)
++        maEntries[i].Clear();
++
++    ClearDestParams();
++}
++
++void ScQueryParam::ClearDestParams()
++{
++    bDestPers = true;
++    nDestTab = 0;
++    nDestCol = 0;
++    nDestRow = 0;
++}
++
++//------------------------------------------------------------------------
++
++ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
++{
++    nCol1       = r.nCol1;
++    nRow1       = r.nRow1;
++    nCol2       = r.nCol2;
++    nRow2       = r.nRow2;
++    nTab        = r.nTab;
++    nDestTab    = r.nDestTab;
++    nDestCol    = r.nDestCol;
++    nDestRow    = r.nDestRow;
++    bHasHeader  = r.bHasHeader;
++    bInplace    = r.bInplace;
++    bCaseSens   = r.bCaseSens;
++    bRegExp     = r.bRegExp;
++    bMixedComparison = r.bMixedComparison;
++    bDuplicate  = r.bDuplicate;
++    bByRow      = r.bByRow;
++    bDestPers   = r.bDestPers;
++
++    maEntries = r.maEntries;
++
++    return *this;
++}
++
++//------------------------------------------------------------------------
++
++BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
++{
++    BOOL bEqual = FALSE;
++
++    // Anzahl der Queries gleich?
++    SCSIZE nUsed      = 0;
++    SCSIZE nOtherUsed = 0;
++    SCSIZE nEntryCount = GetEntryCount();
++    SCSIZE nOtherEntryCount = rOther.GetEntryCount();
++
++    while ( nUsed<nEntryCount && maEntries[nUsed].bDoQuery ) ++nUsed;
++    while ( nOtherUsed<nOtherEntryCount && rOther.maEntries[nOtherUsed].bDoQuery )
++        ++nOtherUsed;
++
++    if (   (nUsed       == nOtherUsed)
++        && (nCol1       == rOther.nCol1)
++        && (nRow1       == rOther.nRow1)
++        && (nCol2       == rOther.nCol2)
++        && (nRow2       == rOther.nRow2)
++        && (nTab        == rOther.nTab)
++        && (bHasHeader  == rOther.bHasHeader)
++        && (bByRow      == rOther.bByRow)
++        && (bInplace    == rOther.bInplace)
++        && (bCaseSens   == rOther.bCaseSens)
++        && (bRegExp     == rOther.bRegExp)
++        && (bMixedComparison == rOther.bMixedComparison)
++        && (bDuplicate  == rOther.bDuplicate)
++        && (bDestPers   == rOther.bDestPers)
++        && (nDestTab    == rOther.nDestTab)
++        && (nDestCol    == rOther.nDestCol)
++        && (nDestRow    == rOther.nDestRow) )
++    {
++        bEqual = TRUE;
++        for ( SCSIZE i=0; i<nUsed && bEqual; i++ )
++            bEqual = maEntries[i] == rOther.maEntries[i];
++    }
++    return bEqual;
++}
++
++//------------------------------------------------------------------------
++
++void ScQueryParam::MoveToDest()
++{
++    if (!bInplace)
++    {
++        SCsCOL nDifX = ((SCsCOL) nDestCol) - ((SCsCOL) nCol1);
++        SCsROW nDifY = ((SCsROW) nDestRow) - ((SCsROW) nRow1);
++        SCsTAB nDifZ = ((SCsTAB) nDestTab) - ((SCsTAB) nTab);
++
++        nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
++        nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
++        nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
++        nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
++        nTab  = sal::static_int_cast<SCTAB>( nTab  + nDifZ );
++        size_t n = maEntries.size();
++        for (size_t i=0; i<n; i++)
++            maEntries[i].nField += nDifX;
++
++        bInplace = TRUE;
++    }
++    else
++    {
++        DBG_ERROR("MoveToDest, bInplace == TRUE");
++    }
++}
++
++// ============================================================================
++
++ScDBQueryParamBase::ScDBQueryParamBase(DataType eType) :
++    ScQueryParamBase(),
++    mnField(-1),
++    mbSkipString(true),
++    meType(eType)
++{
++}
++
++ScDBQueryParamBase::~ScDBQueryParamBase()
++{
++}
++
++ScDBQueryParamBase::DataType ScDBQueryParamBase::GetType() const
++{
++    return meType;
++}
++
++// ============================================================================
++
++ScDBQueryParamInternal::ScDBQueryParamInternal() :
++    ScDBQueryParamBase(ScDBQueryParamBase::INTERNAL),
++    ScQueryParamTable()
++{
++}
++
++ScDBQueryParamInternal::~ScDBQueryParamInternal()
++{
++}
++
++// ============================================================================
++
++ScDBQueryParamMatrix::ScDBQueryParamMatrix() :
++    ScDBQueryParamBase(ScDBQueryParamBase::MATRIX)
++{
++}
++
++ScDBQueryParamMatrix::~ScDBQueryParamMatrix()
++{
++}
++
+diff --git sc/source/filter/excel/colrowst.cxx sc/source/filter/excel/colrowst.cxx
+index 174ab20..199dad8 100644
+--- sc/source/filter/excel/colrowst.cxx
++++ sc/source/filter/excel/colrowst.cxx
+@@ -43,6 +43,7 @@
+ #include "xltable.hxx"
+ #include "xistream.hxx"
+ #include "xistyle.hxx"
++#include "queryparam.hxx"
+ 
+ // for filter manager
+ #include "excimp8.hxx"
+diff --git sc/source/filter/excel/xichart.cxx sc/source/filter/excel/xichart.cxx
+index 2d920b0..69ead7f 100644
+--- sc/source/filter/excel/xichart.cxx
++++ sc/source/filter/excel/xichart.cxx
+@@ -34,6 +34,7 @@
+ #include "xichart.hxx"
+ 
+ #include <algorithm>
++#include <memory>
+ 
+ #include <com/sun/star/frame/XModel.hpp>
+ #include <com/sun/star/drawing/Direction3D.hpp>
+@@ -72,6 +73,8 @@
+ #include "tokenarray.hxx"
+ #include "token.hxx"
+ #include "compiler.hxx"
++#include "reftokenhelper.hxx"
++#include "chartlis.hxx"
+ #include "fprogressbar.hxx"
+ #include "xltracer.hxx"
+ #include "xistream.hxx"
+@@ -123,6 +126,8 @@ using ::com::sun::star::chart2::data::XDataSequence;
+ using ::formula::FormulaToken;
+ using ::formula::StackVar;
+ 
++using ::std::vector;
++
+ // Helpers ====================================================================
+ 
+ namespace {
+@@ -791,6 +796,22 @@ Sequence< Reference< XFormattedString > > XclImpChSourceLink::CreateStringSequen
+     return ScfApiHelper::VectorToSequence( aStringVec );
+ }
+ 
++void XclImpChSourceLink::FillSourceLink(vector<ScSharedTokenRef>& rTokens) const
++{
++    if (!mxTokenArray.is())
++        // no links to fill.
++        return;
++
++    mxTokenArray->Reset();
++    for (FormulaToken* p = mxTokenArray->First(); p; p = mxTokenArray->Next())
++    {
++        ScSharedTokenRef pToken(static_cast<ScToken*>(p->Clone()));
++        if (ScRefTokenHelper::isRef(pToken))
++            // This is a reference token.  Store it.
++            ScRefTokenHelper::join(rTokens, pToken);
++    }
++}
++
+ // Text =======================================================================
+ 
+ XclImpChFontBase::~XclImpChFontBase()
+@@ -1837,6 +1858,14 @@ Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const
+     return xDataSeries;
+ }
+ 
++void XclImpChSeries::FillAllSourceLinks(vector<ScSharedTokenRef>& rTokens) const
++{
++    mxValueLink->FillSourceLink(rTokens);
++    mxCategLink->FillSourceLink(rTokens);
++    mxTitleLink->FillSourceLink(rTokens);
++    mxBubbleLink->FillSourceLink(rTokens);
++}
++
+ void XclImpChSeries::ReadChSourceLink( XclImpStream& rStrm )
+ {
+     XclImpChSourceLinkRef xSrcLink( new XclImpChSourceLink( GetChRoot() ) );
+@@ -3481,7 +3510,7 @@ XclImpChTextRef XclImpChChart::GetDefaultText( XclChTextType eTextType ) const
+     return maDefTexts.get( nDefTextId );
+ }
+ 
+-void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressBar& rProgress ) const
++void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressBar& rProgress, const OUString& rObjName ) const
+ {
+     // initialize conversion (locks the model to suppress any internal updates)
+     InitConversion( xChartDoc );
+@@ -3524,6 +3553,28 @@ void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressB
+ 
+     // unlock the model
+     FinishConversion( rProgress );
++
++    ScDocument* pDoc = &GetRoot().GetDoc();
++    ScChartListenerCollection* pChartCollection = pDoc->GetChartListenerCollection();
++    if (pChartCollection)
++    {
++        // Now, start listening to this chart.
++        ::std::auto_ptr< vector<ScSharedTokenRef> > pRefTokens(new vector<ScSharedTokenRef>);
++        for (XclImpChSeriesVec::const_iterator itr = maSeries.begin(), itrEnd = maSeries.end(); itr != itrEnd; ++itr)
++        {
++            const XclImpChSeriesRef& rSeries = *itr;
++            rSeries->FillAllSourceLinks(*pRefTokens);
++        }
++        if (!pRefTokens->empty())
++        {
++            ::std::auto_ptr<ScChartListener> pListener(
++                new ScChartListener(rObjName, pDoc, pRefTokens.release()));
++            pListener->SetDirty(true);
++            pListener->StartListeningTo();
++            pChartCollection->Insert(pListener.release());
++
++        }
++    }
+ }
+ 
+ void XclImpChChart::ReadChSeries( XclImpStream& rStrm )
+@@ -3749,11 +3800,11 @@ sal_Size XclImpChart::GetProgressSize() const
+     return mxChartData.is() ? mxChartData->GetProgressSize() : 0;
+ }
+ 
+-void XclImpChart::Convert( Reference< XModel > xModel, ScfProgressBar& rProgress ) const
++void XclImpChart::Convert( Reference< XModel > xModel, ScfProgressBar& rProgress, const OUString& rObjName ) const
+ {
+     Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
+     if( mxChartData.is() && xChartDoc.is() )
+-        mxChartData->Convert( xChartDoc, rProgress );
++        mxChartData->Convert( xChartDoc, rProgress, rObjName );
+ }
+ 
+ void XclImpChart::ReadChChart( XclImpStream& rStrm )
+diff --git sc/source/filter/excel/xiescher.cxx sc/source/filter/excel/xiescher.cxx
+index 599b33f..48406eb 100644
+--- sc/source/filter/excel/xiescher.cxx
++++ sc/source/filter/excel/xiescher.cxx
+@@ -1579,7 +1579,7 @@ SdrObject* XclImpChartObj::DoCreateSdrObj( const Rectangle& rAnchorRect, ScfProg
+         if( svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) )
+         {
+             Reference< XModel > xModel( xEmbObj->getComponent(), UNO_QUERY );
+-            mxChart->Convert( xModel, rProgress );
++            mxChart->Convert( xModel, rProgress, aEmbObjName );
+ 
+             Reference< XEmbedPersist > xPers( xEmbObj, UNO_QUERY );
+             if( xPers.is() )
+diff --git sc/source/filter/inc/excimp8.hxx sc/source/filter/inc/excimp8.hxx
+index fadad41..43e630d 100644
+--- sc/source/filter/inc/excimp8.hxx
++++ sc/source/filter/inc/excimp8.hxx
+@@ -37,6 +37,7 @@
+ #include "excscen.hxx"
+ #include "excdefs.hxx"
+ #include "ftools.hxx"
++#include "queryparam.hxx"
+ 
+ class SotStorage;
+ 
+diff --git sc/source/filter/inc/xichart.hxx sc/source/filter/inc/xichart.hxx
+index 1798242..e923ee1 100644
+--- sc/source/filter/inc/xichart.hxx
++++ sc/source/filter/inc/xichart.hxx
+@@ -39,6 +39,7 @@
+ #include <svtools/itemset.hxx>
+ 
+ #include "rangelst.hxx"
++#include "token.hxx"
+ #include "xlchart.hxx"
+ #include "xlstyle.hxx"
+ #include "xistring.hxx"
+@@ -403,6 +404,8 @@ public:
+     XFormattedStringSeq CreateStringSequence( const XclImpChRoot& rRoot,
+                             sal_uInt16 nLeadFontIdx, const Color& rLeadFontColor ) const;
+ 
++    void                FillSourceLink(::std::vector<ScSharedTokenRef>& rTokens) const;
++
+ private:
+     XclChSourceLink     maData;             /// Contents of the CHSOURCELINK record.
+     XclImpStringRef     mxString;           /// Text data (CHSTRING record).
+@@ -811,6 +814,8 @@ public:
+     /** Creates a data series object with initialized source links. */
+     XDataSeriesRef      CreateDataSeries() const;
+ 
++    void                FillAllSourceLinks(::std::vector<ScSharedTokenRef>& rTokens) const;
++
+ private:
+     /** Reads a CHSOURCELINK record. */
+     void                ReadChSourceLink( XclImpStream& rStrm );
+@@ -1353,7 +1358,7 @@ public:
+     inline sal_Size     GetProgressSize() const { return 2 * EXC_CHART_PROGRESS_SIZE; }
+ 
+     /** Converts and writes all properties to the passed chart. */
+-    void                Convert( XChartDocRef xChartDoc, ScfProgressBar& rProgress ) const;
++    void                Convert( XChartDocRef xChartDoc, ScfProgressBar& rProgress, const ::rtl::OUString& rObjName ) const;
+ 
+ private:
+     /** Reads a CHSERIES group (data series source and formatting). */
+@@ -1421,7 +1426,7 @@ public:
+     inline bool         IsPivotChart() const { return mbIsPivotChart; }
+ 
+     /** Creates the chart object in the passed component. */
+-    void                Convert( XModelRef xModel, ScfProgressBar& rProgress ) const;
++    void                Convert( XModelRef xModel, ScfProgressBar& rProgress, const ::rtl::OUString& rObjName ) const;
+ 
+ private:
+     /** Reads the CHCHART group (entire chart data). */
+diff --git sc/source/filter/xml/XMLExportDataPilot.hxx sc/source/filter/xml/XMLExportDataPilot.hxx
+index a3f6cf8..46a2bb0 100644
+--- sc/source/filter/xml/XMLExportDataPilot.hxx
++++ sc/source/filter/xml/XMLExportDataPilot.hxx
+@@ -44,6 +44,7 @@ class ScDPDimensionSaveData;
+ class ScDPSaveGroupDimension;
+ class ScDPSaveNumGroupDimension;
+ struct ScDPNumGroupInfo;
++struct ScQueryParam;
+ 
+ class ScXMLExportDataPilot
+ {
+diff --git sc/source/filter/xml/xmldpimp.hxx sc/source/filter/xml/xmldpimp.hxx
+index b4df6b1..705dbac 100644
+--- sc/source/filter/xml/xmldpimp.hxx
++++ sc/source/filter/xml/xmldpimp.hxx
+@@ -40,6 +40,7 @@
+ #include "global.hxx"
+ #include "dpobject.hxx"
+ #include "dpsave.hxx"
++#include "queryparam.hxx"
+ 
+ #include <hash_set>
+ 
+diff --git sc/source/ui/dbgui/foptmgr.cxx sc/source/ui/dbgui/foptmgr.cxx
+index ee5f039..a425836 100644
+--- sc/source/ui/dbgui/foptmgr.cxx
++++ sc/source/ui/dbgui/foptmgr.cxx
+@@ -45,6 +45,7 @@
+ #include "dbcolect.hxx"
+ #include "viewdata.hxx"
+ #include "document.hxx"
++#include "queryparam.hxx"
+ 
+ #define _FOPTMGR_CXX
+ #include "foptmgr.hxx"
+diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
+index 1f77d2c..f1587bc 100644
+--- sc/source/ui/docshell/externalrefmgr.cxx
++++ sc/source/ui/docshell/externalrefmgr.cxx
+@@ -1045,8 +1045,11 @@ void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rV
+     else
+     {
+         // The source document has changed.
++        ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell();
++        ScDocShellModificator aMod(*pDocShell);
+         pMgr->switchSrcFile(mnFileId, aFile);
+         maFilterName = aFilter;
++        aMod.SetDocumentModified();
+     }
+ }
+ 
+diff --git sc/source/ui/inc/pfiltdlg.hxx sc/source/ui/inc/pfiltdlg.hxx
+index a9ba0d1..b383173 100644
+--- sc/source/ui/inc/pfiltdlg.hxx
++++ sc/source/ui/inc/pfiltdlg.hxx
+@@ -53,8 +53,8 @@
+ #ifndef _COMBOBOX_HXX //autogen
+ #include <vcl/combobox.hxx>
+ #endif
+-#include "global.hxx" // -> ScQueryParam
+ #include "address.hxx"
++#include "queryparam.hxx"
+ 
+ //------------------------------------------------------------------
+ 
+diff --git sc/source/ui/inc/uiitems.hxx sc/source/ui/inc/uiitems.hxx
+index 6581436..4cd4e58 100644
+--- sc/source/ui/inc/uiitems.hxx
++++ sc/source/ui/inc/uiitems.hxx
+@@ -34,6 +34,7 @@
+ #include "scdllapi.h"
+ #include "conditio.hxx"
+ #include "sortparam.hxx"
++#include "queryparam.hxx"
+ #include "paramisc.hxx"
+ #include <svtools/poolitem.hxx>
+ 
+diff --git sc/source/ui/inc/undodat.hxx sc/source/ui/inc/undodat.hxx
+index fb42d81..ad46cb7 100644
+--- sc/source/ui/inc/undodat.hxx
++++ sc/source/ui/inc/undodat.hxx
+@@ -36,6 +36,7 @@
+ #include "rangelst.hxx"		// ScRangeListRef
+ #include "markdata.hxx"
+ #include "sortparam.hxx"
++#include "queryparam.hxx"
+ #include "pivot.hxx"
+ 
+ class ScDocShell;
+diff --git sc/source/ui/undo/undobase.cxx sc/source/ui/undo/undobase.cxx
+index f20abdb..8b59f80 100644
+--- sc/source/ui/undo/undobase.cxx
++++ sc/source/ui/undo/undobase.cxx
+@@ -45,6 +45,7 @@
+ #include "undodraw.hxx"
+ #include "dbcolect.hxx"
+ #include "attrib.hxx"
++#include "queryparam.hxx"
+ #include "globstr.hrc"
+ 
+ // STATIC DATA -----------------------------------------------------------
+diff --git sc/source/ui/unoobj/chart2uno.cxx sc/source/ui/unoobj/chart2uno.cxx
+index 6e8ae0a..877e244 100644
+--- sc/source/ui/unoobj/chart2uno.cxx
++++ sc/source/ui/unoobj/chart2uno.cxx
+@@ -2919,6 +2919,9 @@ void ScChart2DataSequence::BuildDataCache()
+     ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end();
+     for (;itr != itrEnd; ++itr, ++pArr)
+         *pArr = *itr;
++
++    // Clear the data series cache when the array is re-built.
++    m_aMixedDataCache.realloc(0);
+ }
+ 
+ void ScChart2DataSequence::RebuildDataCache()
+@@ -3111,7 +3114,6 @@ void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint
+             if ( m_bGotDataChangedHint && m_pDocument )
+             {        
+                 m_aDataArray.clear();
+-                m_aDataArray.clear();
+                 lang::EventObject aEvent;
+                 aEvent.Source.set((cppu::OWeakObject*)this);
+ 
+@@ -3286,19 +3288,24 @@ uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
+         throw uno::RuntimeException();
+ 
+     BuildDataCache();
+-    sal_Int32 nCount = m_aDataArray.size();
+-    uno::Sequence<uno::Any> aSeq(nCount);
+-    uno::Any* pArr = aSeq.getArray();
+-    ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
+-    for (; itr != itrEnd; ++itr, ++pArr)
++
++    if (!m_aMixedDataCache.getLength())
+     {
+-        if (itr->mbIsValue)
+-            *pArr <<= itr->mfValue;
+-        else
+-            *pArr <<= itr->maString;
+-    }
++        // Build a cache for the 1st time...
+ 
+-    return aSeq;
++        sal_Int32 nCount = m_aDataArray.size();
++        m_aMixedDataCache.realloc(nCount);
++        uno::Any* pArr = m_aMixedDataCache.getArray();
++        ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
++        for (; itr != itrEnd; ++itr, ++pArr)
++        {
++            if (itr->mbIsValue)
++                *pArr <<= itr->mfValue;
++            else
++                *pArr <<= itr->maString;
++        }
++    }
++    return m_aMixedDataCache;
+ }
+ 
+ // XNumericalDataSequence --------------------------------------------------
+diff --git sc/source/ui/view/gridwin4.cxx sc/source/ui/view/gridwin4.cxx
+index 1cd54a2..5428aa1 100644
+--- sc/source/ui/view/gridwin4.cxx
++++ sc/source/ui/view/gridwin4.cxx
+@@ -74,6 +74,7 @@
+ #include "inputopt.hxx"
+ #include "fillinfo.hxx"
+ #include "dpcontrol.hxx"
++#include "queryparam.hxx"
+ #include "sc.hrc"
+ #include <vcl/virdev.hxx>
+ 
diff --git a/patches/dev300/cws-kohei03-sc.diff b/patches/dev300/cws-kohei03-sc.diff
index bbd5526..0b1f33b 100644
--- a/patches/dev300/cws-kohei03-sc.diff
+++ b/patches/dev300/cws-kohei03-sc.diff
@@ -183,7 +183,7 @@ index d5d4235..350c611 100644
  {								// bei SubTotal aber keine ausgeblendeten und
  private:						// SubTotalZeilen
 diff --git sc/inc/document.hxx sc/inc/document.hxx
-index 240765d..d01ee71 100644
+index b6f5001..768e1ad 100644
 --- sc/inc/document.hxx
 +++ sc/inc/document.hxx
 @@ -227,7 +227,7 @@ class ScDocument
@@ -480,7 +480,7 @@ index 2ae9972..09da3d6 100644
  }
  
 diff --git sc/source/core/data/dociter.cxx sc/source/core/data/dociter.cxx
-index f7f836e..031b70a 100644
+index f7f836e..04a2f32 100644
 --- sc/source/core/data/dociter.cxx
 +++ sc/source/core/data/dociter.cxx
 @@ -47,9 +47,23 @@
@@ -1470,7 +1470,7 @@ index 0000000..0aa577b
 +
 +#endif
 diff --git sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
-index ca21e19..e385a9c 100644
+index 58bc46f..0252f1d 100644
 --- sc/source/core/inc/interpre.hxx
 +++ sc/source/core/inc/interpre.hxx
 @@ -53,7 +53,10 @@ class SbxVariable;
@@ -1484,7 +1484,7 @@ index ca21e19..e385a9c 100644
  
  struct ScCompare
  {
-@@ -301,6 +304,7 @@ void DoubleRefToVars( const ScToken* p,
+@@ -302,6 +305,7 @@ void DoubleRefToVars( const ScToken* p,
          SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
          SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
          BOOL bDontCheckForTableOp = FALSE );
@@ -1492,7 +1492,7 @@ index ca21e19..e385a9c 100644
  void PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
                            SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
                            BOOL bDontCheckForTableOp = FALSE );
-@@ -488,7 +492,7 @@ void ScSubTotal();
+@@ -491,7 +495,7 @@ void ScSubTotal();
  // compatibility). If this was the case then rMissingField is set to TRUE upon
  // return. If rMissingField==FALSE upon call all "missing cases" are considered
  // to be an error.
@@ -1515,7 +1515,7 @@ index e1e3870..a47a669 100644
  
 diff --git sc/source/core/tool/doubleref.cxx sc/source/core/tool/doubleref.cxx
 new file mode 100644
-index 0000000..bb67aad
+index 0000000..e1bba5c
 --- /dev/null
 +++ sc/source/core/tool/doubleref.cxx
 @@ -0,0 +1,568 @@
@@ -2088,10 +2088,10 @@ index 0000000..bb67aad
 +}
 +
 diff --git sc/source/core/tool/interpr1.cxx sc/source/core/tool/interpr1.cxx
-index 29a6884..eff5ea3 100644
+index 531f089..aad8822 100644
 --- sc/source/core/tool/interpr1.cxx
 +++ sc/source/core/tool/interpr1.cxx
-@@ -67,11 +67,14 @@
+@@ -68,11 +68,14 @@
  #include <string.h>
  #include <math.h>
  #include <vector>
@@ -2106,7 +2106,7 @@ index 29a6884..eff5ea3 100644
  
  #define SC_DOUBLE_MAXVALUE  1.7e307
  
-@@ -82,6 +85,8 @@ ScTokenStack* ScInterpreter::pGlobalStack = NULL;
+@@ -83,6 +86,8 @@ ScTokenStack* ScInterpreter::pGlobalStack = NULL;
  BOOL ScInterpreter::bGlobalStackInUse = FALSE;
  
  using namespace formula;
@@ -2115,7 +2115,7 @@ index 29a6884..eff5ea3 100644
  //-----------------------------------------------------------------------------
  // Funktionen
  //-----------------------------------------------------------------------------
-@@ -5619,11 +5624,9 @@ void ScInterpreter::ScSubTotal()
+@@ -5826,11 +5831,9 @@ void ScInterpreter::ScSubTotal()
  #endif
  
  
@@ -2123,12 +2123,12 @@ index 29a6884..eff5ea3 100644
 -        BOOL& rMissingField )
 +ScDBQueryParamBase* ScInterpreter::GetDBParams( BOOL& rMissingField )
  {
-     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::GetDBParams" );
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBParams" );
 -    BOOL bRet = FALSE;
      BOOL bAllowMissingField = FALSE;
      if ( rMissingField )
      {
-@@ -5632,14 +5635,10 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
+@@ -5839,14 +5842,10 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
      }
      if ( GetByte() == 3 )
      {
@@ -2147,7 +2147,7 @@ index 29a6884..eff5ea3 100644
  
          BOOL    bByVal = TRUE;
          double  nVal = 0.0;
-@@ -5695,116 +5694,85 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
+@@ -5902,116 +5901,85 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
                  SetError( errIllegalParameter );
          }
  
@@ -2174,9 +2174,8 @@ index 29a6884..eff5ea3 100644
              else
                  SetError( errIllegalParameter );
          }
--        
+         
 -        if (nGlobalError == 0)
-+
 +        if (nGlobalError)
 +            return NULL;
 +
@@ -2186,9 +2185,7 @@ index 29a6884..eff5ea3 100644
 +        else if (bByVal)
 +            nField = pDBRef->findFieldColumn(static_cast<SCCOL>(nVal));
 +        else
-         {
--            SCCOL   nField = nDBCol1;
--            BOOL    bFound = TRUE;
++        {
 +            sal_uInt16 nErr = 0;    
 +            nField = pDBRef->findFieldColumn(aStr, &nErr);
 +            SetError(nErr);
@@ -2200,10 +2197,12 @@ index 29a6884..eff5ea3 100644
 +        auto_ptr<ScDBQueryParamBase> pParam( pDBRef->createQueryParam(pQueryRef.get()) );
 +
 +        if (pParam.get())
-+        {
+         {
+-            SCCOL   nField = nDBCol1;
+-            BOOL    bFound = TRUE;
 +            // An allowed missing field parameter sets the result field
 +            // to any of the query fields, just to be able to return
-+            // some cell from the iterator.        
++            // some cell from the iterator.
              if ( rMissingField )
 -                ;   // special case
 -            else if ( bByVal )
@@ -2295,7 +2294,7 @@ index 29a6884..eff5ea3 100644
  
  void ScInterpreter::DBIterator( ScIterFunc eFunc )
  {
-     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::DBIterator" );
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DBIterator" );
 -    SCTAB nTab1;
      double nErg = 0.0;
      double fMem = 0.0;
@@ -2317,7 +2316,7 @@ index 29a6884..eff5ea3 100644
          {
              switch( eFunc )
              {
-@@ -5820,24 +5788,24 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc )
+@@ -6027,24 +5995,24 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc )
                  {
                      case ifAVERAGE:
                      case ifSUM:
@@ -2351,10 +2350,10 @@ index 29a6884..eff5ea3 100644
      }
      else
          SetError( errIllegalParameter);
-@@ -5862,13 +5830,12 @@ void ScInterpreter::ScDBSum()
+@@ -6069,13 +6037,12 @@ void ScInterpreter::ScDBSum()
  void ScInterpreter::ScDBCount()
  {
-     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScDBCount" );
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount" );
 -    SCTAB nTab;
 -    ScQueryParam aQueryParam;
      BOOL bMissingField = TRUE;
@@ -2368,7 +2367,7 @@ index 29a6884..eff5ea3 100644
          {   // count all matching records
              // TODO: currently the QueryIterators only return cell pointers of
              // existing cells, so if a query matches an empty cell there's
-@@ -5878,7 +5845,9 @@ void ScInterpreter::ScDBCount()
+@@ -6085,7 +6052,9 @@ void ScInterpreter::ScDBCount()
              // have to live with it until we reimplement the iterators to also
              // return empty cells, which would mean to adapt all callers of
              // iterators.
@@ -2379,7 +2378,7 @@ index 29a6884..eff5ea3 100644
              if ( aCellIter.GetFirst() )
              {
                  do
-@@ -5889,17 +5858,17 @@ void ScInterpreter::ScDBCount()
+@@ -6096,17 +6065,17 @@ void ScInterpreter::ScDBCount()
          }
          else
          {   // count only matching records with a value in the "result" field
@@ -2403,10 +2402,10 @@ index 29a6884..eff5ea3 100644
          }
          PushDouble( nCount );
      }
-@@ -5911,21 +5880,24 @@ void ScInterpreter::ScDBCount()
+@@ -6118,21 +6087,24 @@ void ScInterpreter::ScDBCount()
  void ScInterpreter::ScDBCount2()
  {
-     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScDBCount2" );
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount2" );
 -    SCTAB nTab;
 -    ScQueryParam aQueryParam;
      BOOL bMissingField = TRUE;
@@ -2435,7 +2434,7 @@ index 29a6884..eff5ea3 100644
      }
      else
          PushIllegalParameter();
-@@ -5969,25 +5941,23 @@ void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
+@@ -6176,25 +6148,23 @@ void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
  
      rValCount = 0.0;
      double fSum    = 0.0;
@@ -2471,7 +2470,7 @@ index 29a6884..eff5ea3 100644
      else
          SetError( errIllegalParameter);
 diff --git sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
-index cf8dc7e..a301200 100644
+index 1f8fb9e..ffc9978 100644
 --- sc/source/core/tool/interpr4.cxx
 +++ sc/source/core/tool/interpr4.cxx
 @@ -68,15 +68,18 @@
@@ -2493,7 +2492,7 @@ index cf8dc7e..a301200 100644
  
  #define ADDIN_MAXSTRLEN 256
  
-@@ -1021,6 +1024,44 @@ void ScInterpreter::DoubleRefToVars( const ScToken* p,
+@@ -1222,6 +1225,44 @@ void ScInterpreter::DoubleRefToVars( const ScToken* p,
      }
  }
  
@@ -2538,10 +2537,10 @@ index cf8dc7e..a301200 100644
  
  void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
                                   SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
-@@ -1860,78 +1901,37 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
+@@ -2055,78 +2096,37 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
  void ScInterpreter::ScDBGet()
  {
-     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "ScInterpreter::ScDBGet" );
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBGet" );
 -    SCTAB nTab;
 -    ScQueryParam aQueryParam;
      BOOL bMissingField = FALSE;
@@ -3289,16 +3288,16 @@ index ee5f039..a425836 100644
  #define _FOPTMGR_CXX
  #include "foptmgr.hxx"
 diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
-index 1f77d2c..f1587bc 100644
+index 813a6f9..8464799 100644
 --- sc/source/ui/docshell/externalrefmgr.cxx
 +++ sc/source/ui/docshell/externalrefmgr.cxx
-@@ -1045,8 +1045,11 @@ void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rV
+@@ -1057,8 +1057,11 @@ void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rV
      else
      {
          // The source document has changed.
 +        ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell();
 +        ScDocShellModificator aMod(*pDocShell);
-         pMgr->switchSrcFile(mnFileId, aFile);
+         pMgr->switchSrcFile(mnFileId, aFile, aFilter);
          maFilterName = aFilter;
 +        aMod.SetDocumentModified();
      }
@@ -3355,10 +3354,10 @@ index f20abdb..8b59f80 100644
  
  // STATIC DATA -----------------------------------------------------------
 diff --git sc/source/ui/unoobj/chart2uno.cxx sc/source/ui/unoobj/chart2uno.cxx
-index 6e8ae0a..877e244 100644
+index 995a7dc..52e9507 100644
 --- sc/source/ui/unoobj/chart2uno.cxx
 +++ sc/source/ui/unoobj/chart2uno.cxx
-@@ -2919,6 +2919,9 @@ void ScChart2DataSequence::BuildDataCache()
+@@ -2927,6 +2927,9 @@ void ScChart2DataSequence::BuildDataCache()
      ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end();
      for (;itr != itrEnd; ++itr, ++pArr)
          *pArr = *itr;
@@ -3368,7 +3367,7 @@ index 6e8ae0a..877e244 100644
  }
  
  void ScChart2DataSequence::RebuildDataCache()
-@@ -3111,7 +3114,6 @@ void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint
+@@ -3119,7 +3122,6 @@ void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint
              if ( m_bGotDataChangedHint && m_pDocument )
              {        
                  m_aDataArray.clear();
@@ -3376,7 +3375,7 @@ index 6e8ae0a..877e244 100644
                  lang::EventObject aEvent;
                  aEvent.Source.set((cppu::OWeakObject*)this);
  
-@@ -3286,19 +3288,24 @@ uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
+@@ -3294,19 +3296,24 @@ uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
          throw uno::RuntimeException();
  
      BuildDataCache();


More information about the ooo-build-commit mailing list