[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