[ooo-build-commit] patches/dev300
Kohei Yoshida
kohei at kemper.freedesktop.org
Thu Sep 17 06:31:59 PDT 2009
patches/dev300/apply | 5
patches/dev300/cws-kohei03-sc-m57.diff | 3426 ++++++++++++++++++++++++++
patches/dev300/cws-kohei03-sc.diff | 2
patches/dev300/sc-dbrange-dynamic-resize.diff | 995 -------
4 files changed, 3531 insertions(+), 897 deletions(-)
New commits:
commit e0dbbed42627ae2fbadaae712db79d1ad39c49e0
Author: Kohei Yoshida <kyoshida at novell.com>
Date: Thu Sep 17 09:24:48 2009 -0400
Patch massaging for dev300-m58.
* patches/dev300/apply:
* patches/dev300/cws-kohei03-sc-m57.diff:
* patches/dev300/cws-kohei03-sc.diff: branched this patch
for dev300-m58.
* patches/dev300/sc-dbrange-dynamic-resize.diff: somehow I had
managed to screw this patch in my previous commit. Hopefully
fixed this.
diff --git a/patches/dev300/apply b/patches/dev300/apply
index dd16720..44a16b7 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -193,8 +193,13 @@ cws-koheicsvimport-sc.diff, kohei
# kohei03 cws
cws-kohei03-chart2.diff, kohei
+
+[ CWSBackports >= dev300-m58 ]
cws-kohei03-sc.diff, kohei
+[ CWSBackports < dev300-m58 ]
+cws-kohei03-sc-m57.diff, kohei
+
[ LinuxOnly ]
# Don't stat tons of config files we don't need to read on startup
speed-configmgr.diff, i#56783, michael
diff --git a/patches/dev300/cws-kohei03-sc-m57.diff b/patches/dev300/cws-kohei03-sc-m57.diff
new file mode 100644
index 0000000..b008d67
--- /dev/null
+++ b/patches/dev300/cws-kohei03-sc-m57.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::pCaseCollator : *ScGlobal::pCollator;
++
++ 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::pTransliteration->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 b008d67..491a270 100644
--- a/patches/dev300/cws-kohei03-sc.diff
+++ b/patches/dev300/cws-kohei03-sc.diff
@@ -805,7 +805,7 @@ index f7f836e..031b70a 100644
+ aResults.reserve(nEntryCount);
+
+ const CollatorWrapper& rCollator =
-+ mpParam->bCaseSens ? *ScGlobal::pCaseCollator : *ScGlobal::pCollator;
++ mpParam->bCaseSens ? *ScGlobal::GetCaseCollator() : *ScGlobal::GetCollator();
+
+ for (SCSIZE i = 0; i < nEntryCount; ++i)
+ {
diff --git a/patches/dev300/sc-dbrange-dynamic-resize.diff b/patches/dev300/sc-dbrange-dynamic-resize.diff
index 0d1235e..3236a74 100644
--- a/patches/dev300/sc-dbrange-dynamic-resize.diff
+++ b/patches/dev300/sc-dbrange-dynamic-resize.diff
@@ -1,27 +1,8 @@
-diff --git sc/inc/column.hxx sc/inc/column.hxx
-index d49f85b..355f30d 100644
---- sc/inc/column.hxx
-+++ sc/inc/column.hxx
-@@ -378,7 +378,7 @@ public:
- /// Including current, may return -1
- SCsROW GetNextUnprotected( SCROW nRow, BOOL bUp ) const;
-
-- void GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings);
-+ void GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings, bool& rHasDates);
- BOOL GetDataEntries(SCROW nRow, TypedScStrCollection& rStrings, BOOL bLimit);
-
- //UNUSED2008-05 SCROW NoteCount( SCROW nMaxRow = MAXROW ) const;
diff --git sc/inc/dbcolect.hxx sc/inc/dbcolect.hxx
-index 48d314e..00ea53b 100644
+index eea9076..00ea53b 100644
--- sc/inc/dbcolect.hxx
+++ sc/inc/dbcolect.hxx
-@@ -88,11 +88,13 @@ private:
- SCCOLROW nQueryField[MAXQUERY];
- ScQueryOp eQueryOp[MAXQUERY];
- BOOL bQueryByString[MAXQUERY];
-+ bool bQueryByDate[MAXQUERY];
- String* pQueryStr[MAXQUERY];
- double nQueryVal[MAXQUERY];
+@@ -94,6 +94,7 @@ private:
ScQueryConnect eQueryConnect[MAXQUERY];
BOOL bIsAdvanced; // TRUE if created by advanced filter
ScRange aAdvSource; // source range
@@ -29,7 +10,7 @@ index 48d314e..00ea53b 100644
// SubTotalParam
BOOL bSubRemoveOnly;
BOOL bSubReplace;
-@@ -140,9 +142,10 @@ public:
+@@ -141,9 +142,10 @@ public:
const String& GetName() const { return aName; }
void GetName(String& rName) const { rName = aName; }
void SetName(const String& rName) { aName = rName; }
@@ -43,7 +24,7 @@ index 48d314e..00ea53b 100644
BOOL IsByRow() const { return bByRow; }
void SetByRow(BOOL bByR) { bByRow = bByR; }
diff --git sc/inc/document.hxx sc/inc/document.hxx
-index 3a38dde..daeb91e 100644
+index a92545f..daeb91e 100644
--- sc/inc/document.hxx
+++ sc/inc/document.hxx
@@ -873,7 +873,7 @@ public:
@@ -55,7 +36,7 @@ index 3a38dde..daeb91e 100644
SC_DLLPUBLIC BOOL GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const;
SC_DLLPUBLIC BOOL GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const;
SC_DLLPUBLIC BOOL GetPrintArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow,
-@@ -1392,10 +1392,13 @@ public:
+@@ -1392,6 +1392,9 @@ public:
SCTAB nTab, ScQueryParam& rQueryParam );
void GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, String& rStr);
@@ -63,44 +44,23 @@ index 3a38dde..daeb91e 100644
+ void UpdateDynamicEndRow(ScDBData& rDBData) const;
+
BOOL GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
-- TypedScStrCollection& rStrings, bool bFilter = false );
-+ bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates);
+ bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates);
SC_DLLPUBLIC BOOL GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
-- SCTAB nTab, TypedScStrCollection& rStrings );
-+ SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates );
- BOOL GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
- TypedScStrCollection& rStrings, BOOL bLimit = FALSE );
- BOOL GetFormulaEntries( TypedScStrCollection& rStrings );
-diff --git sc/inc/global.hxx sc/inc/global.hxx
-index b401cb9..64cf3b8 100644
---- sc/inc/global.hxx
-+++ sc/inc/global.hxx
-@@ -797,6 +797,7 @@ struct ScQueryEntry
- {
- BOOL bDoQuery;
- BOOL bQueryByString;
-+ bool bQueryByDate;
- SCCOLROW nField;
- ScQueryOp eOp;
- ScQueryConnect eConnect;
-diff --git sc/inc/rangeutl.hxx sc/inc/rangeutl.hxx
-index 1e8d5da..1dc463d 100644
---- sc/inc/rangeutl.hxx
-+++ sc/inc/rangeutl.hxx
-@@ -38,6 +38,11 @@
- #include <com/sun/star/table/CellRangeAddress.hpp>
- #include <com/sun/star/uno/Sequence.hxx>
-
-+// Chart always stores cell range addresses using CONV_OOO convention. But
-+// if parsing with CONV_OOO fails, try parsing it using the current address
-+// convention.
-+#define CHART_ADDRESS_CONV_WORKAROUND 1
-+
- //------------------------------------------------------------------------
+diff --git sc/inc/queryparam.hxx sc/inc/queryparam.hxx
+index bc50237..01ddffb 100644
+--- sc/inc/queryparam.hxx
++++ sc/inc/queryparam.hxx
+@@ -86,6 +86,8 @@ struct SC_DLLPUBLIC ScQueryParam : public ScQueryParamBase, public ScQueryParamT
+ SCTAB nDestTab;
+ SCCOL nDestCol;
+ SCROW nDestRow;
++ SCROW nDynamicEndRow;
++ bool bUseDynamicRange;
- class SvStream;
+ ScQueryParam();
+ ScQueryParam( const ScQueryParam& r );
diff --git sc/inc/table.hxx sc/inc/table.hxx
-index 481cb8c..89f505e 100644
+index 3659381..89f505e 100644
--- sc/inc/table.hxx
+++ sc/inc/table.hxx
@@ -379,7 +379,7 @@ public:
@@ -112,93 +72,11 @@ index 481cb8c..89f505e 100644
SCSIZE GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow,
SCCOL nEndCol, SCROW nEndRow, ScDirection eDir );
-@@ -643,8 +643,8 @@ public:
- SCSIZE Query(ScQueryParam& rQueryParam, BOOL bKeepSub);
- BOOL CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
-
-- void GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings);
-- void GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings );
-+ void GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings, bool& rHasDates);
-+ void GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings, bool& rHasDates );
- BOOL GetDataEntries(SCCOL nCol, SCROW nRow, TypedScStrCollection& rStrings, BOOL bLimit);
-
- BOOL HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow );
-diff --git sc/inc/tabprotection.hxx sc/inc/tabprotection.hxx
-index fc38a1b..99fec7b 100644
---- sc/inc/tabprotection.hxx
-+++ sc/inc/tabprotection.hxx
-@@ -38,7 +38,7 @@
- #include <vector>
- #include <boost/shared_ptr.hpp>
-
--#define ENABLE_SHEET_PROTECTION 0
-+#define ENABLE_SHEET_PROTECTION 1
-
- class ScDocument;
- class ScTableProtectionImpl;
-diff --git sc/source/core/data/column2.cxx sc/source/core/data/column2.cxx
-index 9fc2ea5..2291859 100644
---- sc/source/core/data/column2.cxx
-+++ sc/source/core/data/column2.cxx
-@@ -1319,6 +1319,10 @@ BOOL ScColumn::IsEmpty() const
-
- BOOL ScColumn::IsEmptyBlock(SCROW nStartRow, SCROW nEndRow, bool bIgnoreNotes) const
- {
-+ Rectangle aRect;
-+ if (pAttrArray->HasLines(nStartRow, nEndRow, aRect, TRUE, TRUE))
-+ return FALSE;
-+
- if ( nCount == 0 || !pItems )
- return TRUE;
-
-diff --git sc/source/core/data/column3.cxx sc/source/core/data/column3.cxx
-index 242c5c0..560801d 100644
---- sc/source/core/data/column3.cxx
-+++ sc/source/core/data/column3.cxx
-@@ -1470,8 +1470,9 @@ BOOL ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString,
- }
-
-
--void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings)
-+void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings, bool& rHasDates)
- {
-+ bool bHasDates = false;
- SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
- String aString;
- SCROW nRow = 0;
-@@ -1507,6 +1508,18 @@ void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollec
- nValue = 0.0;
- }
-
-+ if (pFormatter)
-+ {
-+ short nType = pFormatter->GetType(nFormat);
-+ if ((nType & NUMBERFORMAT_DATE) && !(nType & NUMBERFORMAT_TIME))
-+ {
-+ // special case for date values. Disregard the time
-+ // element if the number format is of date type.
-+ nValue = ::rtl::math::approxFloor(nValue);
-+ bHasDates = true;
-+ }
-+ }
-+
- pData = new TypedStrData( aString, nValue, SC_STRTYPE_VALUE );
- }
- #if 0 // DR
-@@ -1525,6 +1538,8 @@ void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollec
-
- ++nIndex;
- }
-+
-+ rHasDates = bHasDates;
- }
-
- //
diff --git sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
-index f0806eb..396d54c 100644
+index caeb5b1..396d54c 100644
--- sc/source/core/data/documen3.cxx
+++ sc/source/core/data/documen3.cxx
-@@ -1255,17 +1255,31 @@ BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol,
+@@ -1255,6 +1255,18 @@ BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol,
//return FALSE;
}
@@ -217,13 +95,7 @@ index f0806eb..396d54c 100644
//
// GetFilterEntries - Eintraege fuer AutoFilter-Listbox
//
-
--BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScStrCollection& rStrings, bool bFilter )
-+BOOL ScDocument::GetFilterEntries(
-+ SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates)
- {
- if ( ValidTab(nTab) && pTab[nTab] && pDBCollection )
- {
+@@ -1267,6 +1279,7 @@ BOOL ScDocument::GetFilterEntries(
ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, FALSE); //!??
if (pDBData)
{
@@ -231,7 +103,7 @@ index f0806eb..396d54c 100644
SCTAB nAreaTab;
SCCOL nStartCol;
SCROW nStartRow;
-@@ -1277,6 +1291,7 @@ BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScSt
+@@ -1278,6 +1291,7 @@ BOOL ScDocument::GetFilterEntries(
ScQueryParam aParam;
pDBData->GetQueryParam( aParam );
@@ -239,34 +111,6 @@ index f0806eb..396d54c 100644
rStrings.SetCaseSensitive( aParam.bCaseSens );
// return all filter entries, if a filter condition is connected with a boolean OR
-@@ -1296,11 +1311,11 @@ BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScSt
-
- if ( bFilter )
- {
-- pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings );
-+ pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates );
- }
- else
- {
-- pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
-+ pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
- }
-
- return TRUE;
-@@ -1315,11 +1330,11 @@ BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScSt
- //
-
- BOOL ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
-- SCTAB nTab, TypedScStrCollection& rStrings )
-+ SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates )
- {
- if ( ValidTab(nTab) && pTab[nTab] )
- {
-- pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
-+ pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
- return TRUE;
- }
-
diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
index 3d61f28..187199f 100644
--- sc/source/core/data/document.cxx
@@ -280,90 +124,6 @@ index 3d61f28..187199f 100644
{
if (VALIDTAB(nTab))
if (pTab[nTab])
-diff --git sc/source/core/data/global2.cxx sc/source/core/data/global2.cxx
-index 181c634..6f3c424 100644
---- sc/source/core/data/global2.cxx
-+++ sc/source/core/data/global2.cxx
-@@ -145,30 +145,32 @@ BOOL ScImportParam::operator==( const ScImportParam& rOther ) const
- //------------------------------------------------------------------------
- // struct ScQueryParam:
-
--ScQueryEntry::ScQueryEntry()
-+ScQueryEntry::ScQueryEntry() :
-+ bDoQuery(FALSE),
-+ bQueryByString(FALSE),
-+ bQueryByDate(false),
-+ nField(0),
-+ eOp(SC_EQUAL),
-+ eConnect(SC_AND),
-+ pStr(new String),
-+ nVal(0.0),
-+ pSearchParam(NULL),
-+ pSearchText(NULL)
-+{
-+}
-+
-+ScQueryEntry::ScQueryEntry(const ScQueryEntry& r) :
-+ bDoQuery(r.bDoQuery),
-+ bQueryByString(r.bQueryByString),
-+ bQueryByDate(r.bQueryByDate),
-+ nField(r.nField),
-+ eOp(r.eOp),
-+ eConnect(r.eConnect),
-+ pStr(new String(*r.pStr)),
-+ nVal(r.nVal),
-+ pSearchParam(NULL),
-+ pSearchText(NULL)
- {
-- bDoQuery = FALSE;
-- bQueryByString = FALSE;
-- eOp = SC_EQUAL;
-- eConnect = SC_AND;
-- nField = 0;
-- nVal = 0.0;
-- pStr = new String;
-- pSearchParam = NULL;
-- pSearchText = NULL;
--}
--
--ScQueryEntry::ScQueryEntry(const ScQueryEntry& r)
--{
-- bDoQuery = r.bDoQuery;
-- bQueryByString = r.bQueryByString;
-- eOp = r.eOp;
-- eConnect = r.eConnect;
-- nField = r.nField;
-- nVal = r.nVal;
-- pStr = new String(*r.pStr);
-- pSearchParam = NULL;
-- pSearchText = NULL;
- }
-
- ScQueryEntry::~ScQueryEntry()
-@@ -185,6 +187,7 @@ ScQueryEntry& ScQueryEntry::operator=( const ScQueryEntry& r )
- {
- bDoQuery = r.bDoQuery;
- bQueryByString = r.bQueryByString;
-+ bQueryByDate = r.bQueryByDate;
- eOp = r.eOp;
- eConnect = r.eConnect;
- nField = r.nField;
-@@ -205,6 +208,7 @@ void ScQueryEntry::Clear()
- {
- bDoQuery = FALSE;
- bQueryByString = FALSE;
-+ bQueryByDate = false;
- eOp = SC_EQUAL;
- eConnect = SC_AND;
- nField = 0;
-@@ -223,6 +227,7 @@ BOOL ScQueryEntry::operator==( const ScQueryEntry& r ) const
- {
- return bDoQuery == r.bDoQuery
- && bQueryByString == r.bQueryByString
-+ && bQueryByDate == r.bQueryByDate
- && eOp == r.eOp
- && eConnect == r.eConnect
- && nField == r.nField
diff --git sc/source/core/data/table1.cxx sc/source/core/data/table1.cxx
index 15db733..10b8cda 100644
--- sc/source/core/data/table1.cxx
@@ -378,39 +138,10 @@ index 15db733..10b8cda 100644
BOOL bLeft = FALSE;
BOOL bRight = FALSE;
diff --git sc/source/core/data/table3.cxx sc/source/core/data/table3.cxx
-index 390f6b1..2ecc8c1 100644
+index 986755a..2ecc8c1 100644
--- sc/source/core/data/table3.cxx
+++ sc/source/core/data/table3.cxx
-@@ -61,6 +61,7 @@
- #include "cellform.hxx"
- #include "postit.hxx"
- #include "queryparam.hxx"
-+#include "svtools/zformat.hxx"
-
- #include <vector>
-
-@@ -1144,6 +1145,20 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
- }
- else
- nCellVal = GetValue( static_cast<SCCOL>(rEntry.nField), nRow );
-+
-+ if (rEntry.bQueryByDate)
-+ {
-+ sal_uInt32 nNumFmt = GetNumberFormat(static_cast<SCCOL>(rEntry.nField), nRow);
-+ const SvNumberformat* pEntry = pDocument->GetFormatTable()->GetEntry(nNumFmt);
-+ if (pEntry)
-+ {
-+ short nNumFmtType = pEntry->GetType();
-+ if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
-+ // The format is of date type. Strip off the time element.
-+ nCellVal = ::rtl::math::approxFloor(nCellVal);
-+ }
-+ }
-+
- switch (rEntry.eOp)
- {
- case SC_EQUAL :
-@@ -1602,6 +1617,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
+@@ -1617,6 +1617,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
BOOL* pSpecial = new BOOL[nEntryCount];
lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
@@ -418,7 +149,7 @@ index 390f6b1..2ecc8c1 100644
if (!aParam.bInplace)
{
nOutRow = aParam.nDestRow + nHeader;
-@@ -1610,7 +1626,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
+@@ -1625,7 +1626,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
}
@@ -427,65 +158,11 @@ index 390f6b1..2ecc8c1 100644
{
BOOL bResult; // Filterergebnis
BOOL bValid = ValidQuery(j, aParam, pSpecial);
-@@ -1931,12 +1947,13 @@ BOOL ScTable::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL /* nEndCol *
- return TRUE;
- }
-
--void ScTable::GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings)
-+void ScTable::GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings, bool& rHasDates)
- {
-- aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings );
-+ aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings, rHasDates );
- }
-
--void ScTable::GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings )
-+void ScTable::GetFilteredFilterEntries(
-+ SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings, bool& rHasDates )
- {
- // remove the entry for this column from the query parameter
- ScQueryParam aParam( rParam );
-@@ -1954,15 +1971,18 @@ void ScTable::GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, co
-
- BOOL* pSpecial = new BOOL[nEntryCount];
- lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
--
-+ bool bHasDates = false;
- for ( SCROW j = nRow1; j <= nRow2; ++j )
- {
- if ( ValidQuery( j, aParam, pSpecial ) )
- {
-- aCol[nCol].GetFilterEntries( j, j, rStrings );
-+ bool bThisHasDates = false;
-+ aCol[nCol].GetFilterEntries( j, j, rStrings, bThisHasDates );
-+ bHasDates |= bThisHasDates;
- }
- }
-
-+ rHasDates = bHasDates;
- delete[] pSpecial;
- }
-
diff --git sc/source/core/tool/dbcolect.cxx sc/source/core/tool/dbcolect.cxx
-index 22642f4..5fae4bd 100644
+index 4f0e755..5fae4bd 100644
--- sc/source/core/tool/dbcolect.cxx
+++ sc/source/core/tool/dbcolect.cxx
-@@ -159,6 +159,7 @@ ScDBData::ScDBData( const ScDBData& rData ) :
- nQueryField[i] = rData.nQueryField[i];
- eQueryOp[i] = rData.eQueryOp[i];
- bQueryByString[i] = rData.bQueryByString[i];
-+ bQueryByDate[i] = rData.bQueryByDate[i];
- pQueryStr[i] = new String( *(rData.pQueryStr[i]) );
- nQueryVal[i] = rData.nQueryVal[i];
- eQueryConnect[i] = rData.eQueryConnect[i];
-@@ -249,6 +250,7 @@ ScDBData& ScDBData::operator= (const ScDBData& rData)
- nQueryField[i] = rData.nQueryField[i];
- eQueryOp[i] = rData.eQueryOp[i];
- bQueryByString[i] = rData.bQueryByString[i];
-+ bQueryByDate[i] = rData.bQueryByDate[i];
- *pQueryStr[i] = *rData.pQueryStr[i];
- nQueryVal[i] = rData.nQueryVal[i];
- eQueryConnect[i] = rData.eQueryConnect[i];
-@@ -379,18 +381,20 @@ String ScDBData::GetOperations() const
+@@ -381,18 +381,20 @@ String ScDBData::GetOperations() const
return aVal;
}
@@ -510,7 +187,7 @@ index 22642f4..5fae4bd 100644
}
void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
-@@ -402,6 +406,11 @@ void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW
+@@ -404,6 +406,11 @@ void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW
nEndRow = nRow2;
}
@@ -522,7 +199,7 @@ index 22642f4..5fae4bd 100644
void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
{
USHORT i;
-@@ -509,6 +518,7 @@ void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
+@@ -511,6 +518,7 @@ void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
rQueryParam.nDestTab = nQueryDestTab;
rQueryParam.nDestCol = nQueryDestCol;
rQueryParam.nDestRow = nQueryDestRow;
@@ -530,236 +207,83 @@ index 22642f4..5fae4bd 100644
rQueryParam.Resize( MAXQUERY );
for (SCSIZE i=0; i<MAXQUERY; i++)
-@@ -519,6 +529,7 @@ void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
- rEntry.nField = nQueryField[i];
- rEntry.eOp = eQueryOp[i];
- rEntry.bQueryByString = bQueryByString[i];
-+ rEntry.bQueryByDate = bQueryByDate[i];
- *rEntry.pStr = *pQueryStr[i];
- rEntry.nVal = nQueryVal[i];
- rEntry.eConnect = eQueryConnect[i];
-@@ -550,6 +561,7 @@ void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam)
- nQueryField[i] = rEntry.nField;
- eQueryOp[i] = rEntry.eOp;
- bQueryByString[i] = rEntry.bQueryByString;
-+ bQueryByDate[i] = rEntry.bQueryByDate;
- *pQueryStr[i] = *rEntry.pStr;
- nQueryVal[i] = rEntry.nVal;
- eQueryConnect[i] = rEntry.eConnect;
-diff --git sc/source/core/tool/rangeutl.cxx sc/source/core/tool/rangeutl.cxx
-index 62474c3..b5bdfda 100644
---- sc/source/core/tool/rangeutl.cxx
-+++ sc/source/core/tool/rangeutl.cxx
-@@ -479,6 +479,11 @@ sal_Bool ScRangeStringConverter::GetAddressFromString(
- {
- if ((rAddress.Parse( sToken, const_cast<ScDocument*>(pDocument), eConv ) & SCA_VALID) == SCA_VALID)
- return true;
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+ ::formula::FormulaGrammar::AddressConvention eConvUI = pDocument->GetAddressConvention();
-+ if (eConv != eConvUI)
-+ return ((rAddress.Parse(sToken, const_cast<ScDocument*>(pDocument), eConvUI) & SCA_VALID) == SCA_VALID);
-+#endif
- }
- return sal_False;
- }
-@@ -505,6 +510,11 @@ sal_Bool ScRangeStringConverter::GetRangeFromString(
- if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
- aUIString.Erase( 0, 1 );
- bResult = ((rRange.aStart.Parse( aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID);
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+ if (!bResult && eConv != eConv)
-+ bResult = ((rRange.aStart.Parse(
-+ aUIString, const_cast<ScDocument*>(pDocument), eConv) & SCA_VALID) == SCA_VALID);
-+#endif
- rRange.aEnd = rRange.aStart;
- }
- else
-@@ -529,6 +539,15 @@ sal_Bool ScRangeStringConverter::GetRangeFromString(
- eConv) & SCA_VALID) == SCA_VALID) &&
- ((rRange.aEnd.Parse( aUIString.Copy((xub_StrLen)nIndex+1), const_cast<ScDocument*>(pDocument),
- eConv) & SCA_VALID) == SCA_VALID);
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+ if (!bResult && eConv != eConv)
-+ {
-+ bResult = ((rRange.aStart.Parse( aUIString.Copy(0, (xub_StrLen)nIndex), const_cast<ScDocument*>(pDocument),
-+ eConv) & SCA_VALID) == SCA_VALID) &&
-+ ((rRange.aEnd.Parse( aUIString.Copy((xub_StrLen)nIndex+1), const_cast<ScDocument*>(pDocument),
-+ eConv) & SCA_VALID) == SCA_VALID);
-+ }
-+#endif
- }
- }
- }
-@@ -863,6 +882,8 @@ static void lcl_appendCellRangeAddress(
-
- void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, const OUString& rXMLRange, ScDocument* pDoc )
+diff --git sc/source/core/tool/queryparam.cxx sc/source/core/tool/queryparam.cxx
+index d9d477d..0593534 100644
+--- sc/source/core/tool/queryparam.cxx
++++ sc/source/core/tool/queryparam.cxx
+@@ -177,7 +177,8 @@ ScQueryParam::ScQueryParam() :
+ ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
+ ScQueryParamBase(r),
+ ScQueryParamTable(r),
+- bDestPers(r.bDestPers), nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
++ bDestPers(r.bDestPers), nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow),
++ nDynamicEndRow(r.nDynamicEndRow), bUseDynamicRange(r.bUseDynamicRange)
{
-+ FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
-+ const OUString aRangeSep = GetScCompilerNativeSymbol(ocSep);
- const sal_Unicode cSep = ' ';
- const sal_Unicode cQuote = '\'';
-
-@@ -915,13 +936,37 @@ void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, con
- rtl::OUString aBuf;
- USHORT nRet = aCell1.Parse(aBeginCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo1);
- if ((nRet & SCA_VALID) != SCA_VALID)
-+ {
- // first cell is invalid.
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+ if (eConv == FormulaGrammar::CONV_OOO)
-+ continue;
-+
-+ nRet = aCell1.Parse(aBeginCell, pDoc, eConv, &aExtInfo1);
-+ if ((nRet & SCA_VALID) != SCA_VALID)
-+ // first cell is really invalid.
-+ continue;
-+#else
- continue;
-+#endif
-+ }
-
- nRet = aCell2.Parse(aEndCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo2);
- if ((nRet & SCA_VALID) != SCA_VALID)
-+ {
- // second cell is invalid.
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+ if (eConv == FormulaGrammar::CONV_OOO)
-+ continue;
-+
-+ nRet = aCell2.Parse(aEndCell, pDoc, eConv, &aExtInfo2);
-+ if ((nRet & SCA_VALID) != SCA_VALID)
-+ // second cell is really invalid.
-+ continue;
-+#else
- continue;
-+#endif
-+ }
-
- if (aExtInfo1.mnFileId != aExtInfo2.mnFileId || aExtInfo1.mbExternal != aExtInfo2.mbExternal)
- // external info inconsistency.
-@@ -932,7 +977,7 @@ void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, con
- if (bFirst)
- bFirst = false;
- else
-- aRetStr.appendAscii(";");
-+ aRetStr.append(aRangeSep);
-
- lcl_appendCellRangeAddress(aRetStr, pDoc, aCell1, aCell2, aExtInfo1, aExtInfo2);
- }
-@@ -943,14 +988,22 @@ void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, con
- ScAddress aCell;
- USHORT nRet = aCell.Parse(aToken, pDoc, ::formula::FormulaGrammar::CONV_OOO, &aExtInfo);
- if ((nRet & SCA_VALID) != SCA_VALID)
-+ {
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+ nRet = aCell.Parse(aToken, pDoc, eConv, &aExtInfo);
-+ if ((nRet & SCA_VALID) != SCA_VALID)
-+ continue;
-+#else
- continue;
-+#endif
-+ }
-
- // Looks good!
-
- if (bFirst)
- bFirst = false;
- else
-- aRetStr.appendAscii(";");
-+ aRetStr.append(aRangeSep);
-
- lcl_appendCellAddress(aRetStr, pDoc, aCell, aExtInfo);
- }
-diff --git sc/source/ui/app/inputhdl.cxx sc/source/ui/app/inputhdl.cxx
-index 98aac39..6ac26bc 100644
---- sc/source/ui/app/inputhdl.cxx
-+++ sc/source/ui/app/inputhdl.cxx
-@@ -2055,6 +2055,7 @@ IMPL_LINK( ScInputHandler, ModifyHdl, void *, EMPTYARG )
+ }
- BOOL ScInputHandler::DataChanging( sal_Unicode cTyped, BOOL bFromCommand ) // return TRUE = new view created
+@@ -187,7 +188,9 @@ ScQueryParam::ScQueryParam( const ScDBQueryParamInternal& r ) :
+ bDestPers(true),
+ nDestTab(0),
+ nDestCol(0),
+- nDestRow(0)
++ nDestRow(0),
++ nDynamicEndRow(0),
++ bUseDynamicRange(false)
{
-+ pActiveViewSh->GetViewData()->SetPasteMode( SC_PASTE_NONE );
- bInOwnChange = TRUE; // disable ModifyHdl (reset in DataChanged)
+ }
+
+@@ -221,6 +224,8 @@ void ScQueryParam::ClearDestParams()
+ nDestTab = 0;
+ nDestCol = 0;
+ nDestRow = 0;
++ nDynamicEndRow = 0;
++ bUseDynamicRange = false;
+ }
- if ( eMode == SC_INPUT_NONE )
+ //------------------------------------------------------------------------
+@@ -243,6 +248,8 @@ ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
+ bDuplicate = r.bDuplicate;
+ bByRow = r.bByRow;
+ bDestPers = r.bDestPers;
++ nDynamicEndRow = r.nDynamicEndRow;
++ bUseDynamicRange = r.bUseDynamicRange;
+
+ maEntries = r.maEntries;
+
+@@ -281,7 +288,9 @@ BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
+ && (bDestPers == rOther.bDestPers)
+ && (nDestTab == rOther.nDestTab)
+ && (nDestCol == rOther.nDestCol)
+- && (nDestRow == rOther.nDestRow) )
++ && (nDestRow == rOther.nDestRow)
++ && (nDynamicEndRow == rOther.nDynamicEndRow)
++ && (bUseDynamicRange == rOther.bUseDynamicRange) )
+ {
+ bEqual = TRUE;
+ for ( SCSIZE i=0; i<nUsed && bEqual; i++ )
+@@ -305,6 +314,7 @@ void ScQueryParam::MoveToDest()
+ nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
+ nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
+ nTab = sal::static_int_cast<SCTAB>( nTab + nDifZ );
++ nDynamicEndRow = sal::static_int_cast<SCROW>( nDynamicEndRow + nDifY );
+ size_t n = maEntries.size();
+ for (size_t i=0; i<n; i++)
+ maEntries[i].nField += nDifX;
diff --git sc/source/ui/dbgui/filtdlg.cxx sc/source/ui/dbgui/filtdlg.cxx
-index 4a2d4d4..3491024 100644
+index 4f56adb..51fe845 100644
--- sc/source/ui/dbgui/filtdlg.cxx
+++ sc/source/ui/dbgui/filtdlg.cxx
-@@ -451,24 +451,27 @@ void ScFilterDlg::UpdateValueList( USHORT nList )
- SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
- if (!pEntryLists[nColumn])
- {
-+ USHORT nOffset = GetSliderPos();
+@@ -454,7 +454,7 @@ void ScFilterDlg::UpdateValueList( USHORT nList )
+ USHORT nOffset = GetSliderPos();
SCTAB nTab = nSrcTab;
SCROW nFirstRow = theQueryData.nRow1;
- SCROW nLastRow = theQueryData.nRow2;
-+ SCROW nLastRow = theQueryData.bUseDynamicRange ? theQueryData.nDynamicEndRow : theQueryData.nRow2;
-+ mbHasDates[nOffset+nList-1] = false;
++ SCROW nLastRow = theQueryData.bUseDynamicRange ? theQueryData.nDynamicEndRow : theQueryData.nRow2;
+ mbHasDates[nOffset+nList-1] = false;
// erstmal ohne die erste Zeile
-
- pEntryLists[nColumn] = new TypedScStrCollection( 128, 128 );
- pEntryLists[nColumn]->SetCaseSensitive( aBtnCase.IsChecked() );
- pDoc->GetFilterEntriesArea( nColumn, nFirstRow+1, nLastRow,
-- nTab, *pEntryLists[nColumn] );
-+ nTab, *pEntryLists[nColumn], mbHasDates[nOffset+nList-1] );
-
- // Eintrag fuer die erste Zeile
- //! Eintrag (pHdrEntry) ohne Collection erzeugen?
-
- nHeaderPos[nColumn] = USHRT_MAX;
- TypedScStrCollection aHdrColl( 1, 1 );
-+ bool bDummy = false;
- pDoc->GetFilterEntriesArea( nColumn, nFirstRow, nFirstRow,
-- nTab, aHdrColl );
-+ nTab, aHdrColl, bDummy );
- TypedStrData* pHdrEntry = aHdrColl[0];
- if ( pHdrEntry )
- {
-@@ -1064,7 +1067,8 @@ IMPL_LINK( ScFilterDlg, ValModifyHdl, ComboBox*, pEd )
- static_cast<SCCOL>(nField) - 1) : static_cast<SCCOL>(0);
-
- ScQueryOp eOp = (ScQueryOp)pLbCond->GetSelectEntryPos();
-- rEntry.eOp = eOp;
-+ rEntry.eOp = eOp;
-+ rEntry.bQueryByDate = mbHasDates[nQE];
-
- }
- }
-diff --git sc/source/ui/dbgui/pfiltdlg.cxx sc/source/ui/dbgui/pfiltdlg.cxx
-index 35bfc35..42c2c26 100644
---- sc/source/ui/dbgui/pfiltdlg.cxx
-+++ sc/source/ui/dbgui/pfiltdlg.cxx
-@@ -352,11 +352,12 @@ void ScPivotFilterDlg::UpdateValueList( USHORT nList )
- SCROW nFirstRow = theQueryData.nRow1;
- SCROW nLastRow = theQueryData.nRow2;
- nFirstRow++;
-+ bool bHasDates = false;
-
- pEntryLists[nColumn] = new TypedScStrCollection( 128, 128 );
- pEntryLists[nColumn]->SetCaseSensitive( aBtnCase.IsChecked() );
- pDoc->GetFilterEntriesArea( nColumn, nFirstRow, nLastRow,
-- nTab, *pEntryLists[nColumn] );
-+ nTab, *pEntryLists[nColumn], bHasDates );
- }
-
- TypedScStrCollection* pColl = pEntryLists[nColumn];
-diff --git sc/source/ui/docshell/docsh.cxx sc/source/ui/docshell/docsh.cxx
-index 2e9ad98..e884d14 100644
---- sc/source/ui/docshell/docsh.cxx
-+++ sc/source/ui/docshell/docsh.cxx
-@@ -1924,7 +1924,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
- 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 sc/source/ui/inc/dbfunc.hxx sc/source/ui/inc/dbfunc.hxx
-index 91834e1..f9a76a0 100644
+index 91834e1..097202b 100644
--- sc/source/ui/inc/dbfunc.hxx
+++ sc/source/ui/inc/dbfunc.hxx
@@ -80,7 +80,7 @@ public:
@@ -767,115 +291,12 @@ index 91834e1..f9a76a0 100644
// DB-Bereich vom Cursor
- ScDBData* GetDBData( BOOL bMarkArea = TRUE, ScGetDBMode eMode = SC_DB_MAKE, bool bShrinkToData = false );
-+ ScDBData* GetDBData( BOOL bMarkArea = TRUE, ScGetDBMode eMode = SC_DB_MAKE, bool bExpandRows = false, bool bShrinkToData = false );
++ ScDBData* GetDBData( BOOL bMarkArea = TRUE, ScGetDBMode eMode = SC_DB_MAKE, bool bShrinkToData = false, bool bExpandRows = false );
void NotifyCloseDbNameDlg( const ScDBCollection& rNewColl, const List& rDelAreaList );
-diff --git sc/source/ui/inc/filtdlg.hxx sc/source/ui/inc/filtdlg.hxx
-index c418e82..7409b5a 100644
---- sc/source/ui/inc/filtdlg.hxx
-+++ sc/source/ui/inc/filtdlg.hxx
-@@ -167,6 +167,7 @@ private:
- ListBox* aFieldLbArr[4];
- ListBox* aCondLbArr[4];
- ListBox* aConnLbArr[4];
-+ bool mbHasDates[MAXQUERY];
- BOOL bRefreshExceptQuery[MAXQUERY];
- USHORT nFieldCount;
- BOOL bRefInputMode;
-diff --git sc/source/ui/inc/gridwin.hxx sc/source/ui/inc/gridwin.hxx
-index 4013e1a..aae0353 100644
---- sc/source/ui/inc/gridwin.hxx
-+++ sc/source/ui/inc/gridwin.hxx
-@@ -218,7 +218,7 @@ private:
-
- BOOL IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab );
- void ExecFilter( ULONG nSel, SCCOL nCol, SCROW nRow,
-- const String& aValue );
-+ const String& aValue, bool bCheckForDates );
- void FilterSelect( ULONG nSel );
-
- void ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr );
-diff --git sc/source/ui/inc/preview.hxx sc/source/ui/inc/preview.hxx
-index 2449554..848f22e 100644
---- sc/source/ui/inc/preview.hxx
-+++ sc/source/ui/inc/preview.hxx
-@@ -66,6 +66,8 @@ private:
- ScPreviewLocationData* pLocationData; // stores table layout for accessibility API
- FmFormView* pDrawView;
-
-+ SCTAB nCurTab;
-+
- // intern:
- BOOL bInPaint;
- BOOL bInGetState;
-diff --git sc/source/ui/inc/viewdata.hxx sc/source/ui/inc/viewdata.hxx
-index 6f0d986..19583a8 100644
---- sc/source/ui/inc/viewdata.hxx
-+++ sc/source/ui/inc/viewdata.hxx
-@@ -89,6 +89,13 @@ enum ScMarkType
- #endif
- };
-
-+enum ScPasteFlags
-+{
-+ SC_PASTE_NONE = 0, // No flags specified
-+ SC_PASTE_MODE = 1, // Enable paste-mode
-+ SC_PASTE_BORDER = 2, // Show a border around the source cells
-+};
-+
- class ScDocShell;
- class ScDocument;
- class ScDBFunc;
-@@ -210,6 +217,8 @@ private:
- SCCOL nTabStartCol; // fuer Enter nach Tab
- ScRange aDelRange; // fuer AutoFill-Loeschen
-
-+ ScPasteFlags nPasteFlags;
-+
- ScSplitPos eEditActivePart; // the part that was active when edit mode was started
- BOOL bEditActive[4]; // aktiv?
- BOOL bActive; // aktives Fenster ?
-@@ -295,6 +304,8 @@ public:
- SCCOL GetFixPosX() const { return pThisTab->nFixPosX; }
- SCROW GetFixPosY() const { return pThisTab->nFixPosY; }
- BOOL IsPagebreakMode() const { return bPagebreak; }
-+ BOOL IsPasteMode() const { return nPasteFlags & SC_PASTE_MODE; }
-+ BOOL ShowPasteSource() const { return nPasteFlags & SC_PASTE_BORDER; }
-
- void SetPosX( ScHSplitPos eWhich, SCCOL nNewPosX );
- void SetPosY( ScVSplitPos eWhich, SCROW nNewPosY );
-@@ -309,6 +320,7 @@ public:
- void SetFixPosX( SCCOL nPos ) { pThisTab->nFixPosX = nPos; }
- void SetFixPosY( SCROW nPos ) { pThisTab->nFixPosY = nPos; }
- void SetPagebreakMode( BOOL bSet );
-+ void SetPasteMode ( ScPasteFlags nFlags ) { nPasteFlags = nFlags; }
-
- void SetZoomType( SvxZoomType eNew, BOOL bAll );
- void SetZoom( const Fraction& rNewX, const Fraction& rNewY, BOOL bAll );
-diff --git sc/source/ui/view/cellsh1.cxx sc/source/ui/view/cellsh1.cxx
-index d87d081..19ee659 100644
---- sc/source/ui/view/cellsh1.cxx
-+++ sc/source/ui/view/cellsh1.cxx
-@@ -1170,6 +1170,8 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
- WaitObject aWait( GetViewData()->GetDialogParent() );
- pTabViewShell->CopyToClip( NULL, FALSE, FALSE, TRUE );
- rReq.Done();
-+ GetViewData()->SetPasteMode( (ScPasteFlags) (SC_PASTE_MODE | SC_PASTE_BORDER) );
-+ pTabViewShell->ShowCursor();
- }
- break;
-
-@@ -1178,6 +1180,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
- WaitObject aWait( GetViewData()->GetDialogParent() );
- pTabViewShell->CutToClip( NULL, TRUE );
- rReq.Done();
-+ GetViewData()->SetPasteMode( SC_PASTE_MODE );
- }
- break;
-
diff --git sc/source/ui/view/dbfunc.cxx sc/source/ui/view/dbfunc.cxx
-index 05dce54..fa05fa6 100644
+index 05dce54..e78581a 100644
--- sc/source/ui/view/dbfunc.cxx
+++ sc/source/ui/view/dbfunc.cxx
@@ -107,7 +107,7 @@ void ScDBFunc::GotoDBArea( const String& rDBName )
@@ -883,7 +304,7 @@ index 05dce54..fa05fa6 100644
// aktuellen Datenbereich fuer Sortieren / Filtern suchen
-ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, bool bShrinkToData )
-+ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, bool bExpandRows, bool bShrinkToData )
++ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, bool bShrinkToData, bool bExpandRows )
{
ScDocShell* pDocSh = GetViewData()->GetDocShell();
ScDBData* pData = NULL;
@@ -911,80 +332,10 @@ index 05dce54..fa05fa6 100644
}
return pData;
diff --git sc/source/ui/view/gridwin.cxx sc/source/ui/view/gridwin.cxx
-index b547e2c..57f1996 100644
+index 6e0280a..57f1996 100644
--- sc/source/ui/view/gridwin.cxx
+++ sc/source/ui/view/gridwin.cxx
-@@ -118,6 +118,7 @@
- #include "userdat.hxx"
- #include "drwlayer.hxx"
- #include "attrib.hxx"
-+#include "cellsh.hxx"
- #include "validat.hxx"
- #include "tabprotection.hxx"
- #include "postit.hxx"
-@@ -170,6 +171,7 @@ private:
- BOOL bInit;
- BOOL bCancelled;
- BOOL bInSelect;
-+ bool mbListHasDates;
- ULONG nSel;
- ScFilterBoxMode eMode;
-
-@@ -193,6 +195,8 @@ public:
- BOOL IsInInit() const { return bInit; }
- void SetCancelled() { bCancelled = TRUE; }
- BOOL IsInSelect() const { return bInSelect; }
-+ void SetListHasDates(bool b) { mbListHasDates = b; }
-+ bool HasDates() const { return mbListHasDates; }
- };
-
- //-------------------------------------------------------------------
-@@ -208,6 +212,7 @@ ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
- bInit( TRUE ),
- bCancelled( FALSE ),
- bInSelect( FALSE ),
-+ mbListHasDates(false),
- nSel( 0 ),
- eMode( eNewMode )
- {
-@@ -912,7 +917,9 @@ void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, BOOL bDataSelect )
- pFilterBox->SetSeparatorPos( nDefCount - 1 );
-
- // get list entries
-- pDoc->GetFilterEntries( nCol, nRow, nTab, aStrings, true );
-+ bool bHasDates = false;
-+ pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
-+ pFilterBox->SetListHasDates(bHasDates);
-
- // check widths of numerical entries (string entries are not included)
- // so all numbers are completely visible
-@@ -1122,7 +1129,7 @@ void ScGridWindow::FilterSelect( ULONG nSel )
- ExecDataSelect( nCol, nRow, aString );
- break;
- case SC_FILTERBOX_FILTER:
-- ExecFilter( nSel, nCol, nRow, aString );
-+ ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
- break;
- case SC_FILTERBOX_SCENARIO:
- pViewData->GetView()->UseScenario( aString );
-@@ -1155,7 +1162,7 @@ void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
-
- void ScGridWindow::ExecFilter( ULONG nSel,
- SCCOL nCol, SCROW nRow,
-- const String& aValue )
-+ const String& aValue, bool bCheckForDates )
- {
- SCTAB nTab = pViewData->GetTabNo();
- ScDocument* pDoc = pViewData->GetDocument();
-@@ -1227,6 +1234,7 @@ void ScGridWindow::ExecFilter( ULONG nSel,
- rNewEntry.bDoQuery = TRUE;
- rNewEntry.bQueryByString = TRUE;
- rNewEntry.nField = nCol;
-+ rNewEntry.bQueryByDate = bCheckForDates;
- if ( nSel == SC_AUTOFILTER_TOP10 )
- {
- rNewEntry.eOp = SC_TOPVAL;
-@@ -1268,6 +1276,7 @@ void ScGridWindow::ExecFilter( ULONG nSel,
+@@ -1276,6 +1276,7 @@ void ScGridWindow::ExecFilter( ULONG nSel,
pViewData->GetViewShell()->UpdateInputHandler();
}
@@ -992,122 +343,6 @@ index b547e2c..57f1996 100644
pViewData->GetView()->Query( aParam, NULL, TRUE );
pDBData->SetQueryParam( aParam ); // speichern
}
-@@ -2962,12 +2971,30 @@ void ScGridWindow::SelectForContextMenu( const Point& rPosPixel )
- }
- }
-
-+static void ClearSingleSelection( ScViewData* pViewData )
-+{
-+ SCCOL nX;
-+ SCROW nY;
-+ ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard(
-+ pViewData->GetActiveWin() );
-+ if (!pTransObj)
-+ return;
-+
-+ ScDocument* pClipDoc = pTransObj->GetDocument();
-+ pClipDoc->GetClipArea( nX, nY, TRUE );
-+ if (nX == 0 && nY == 0)
-+ {
-+ ScTabView* pView = pViewData->GetView();
-+ pView->Unmark();
-+ }
-+}
-+
- void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
- {
- // #96965# Cursor control for ref input dialog
-+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
- if( SC_MOD()->IsRefDialogOpen() )
- {
-- const KeyCode& rKeyCode = rKEvt.GetKeyCode();
- if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
- {
- SC_MOD()->EndReference();
-@@ -2982,9 +3009,35 @@ void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
- return;
- }
- }
-+ else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
-+ {
-+ ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
-+
-+ ScCellShell::PasteFromClipboard( pViewData, pTabViewShell, FALSE );
-+ ClearSingleSelection( pViewData );
-+
-+ uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard =
-+ TransferableHelper::GetSystemClipboard();
-+ if (xSystemClipboard.is())
-+ {
-+ xSystemClipboard->setContents(
-+ uno::Reference<datatransfer::XTransferable>(),
-+ uno::Reference<datatransfer::clipboard::XClipboardOwner>());
-+ }
-+
-+ // hide the border around the copy source
-+ pViewData->SetPasteMode( SC_PASTE_NONE );
-+ UpdateCursorOverlay();
-+ return;
-+ }
- // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
- else if( !pViewData->IsAnyFillMode() )
- {
-+ if (rKeyCode.GetCode() == KEY_ESCAPE)
-+ {
-+ pViewData->SetPasteMode( SC_PASTE_NONE );
-+ UpdateCursorOverlay();
-+ }
- // query for existing note marker before calling ViewShell's keyboard handling
- // which may remove the marker
- BOOL bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
-diff --git sc/source/ui/view/preview.cxx sc/source/ui/view/preview.cxx
-index d1e59ca..0756c8f 100644
---- sc/source/ui/view/preview.cxx
-+++ sc/source/ui/view/preview.cxx
-@@ -112,6 +112,7 @@ ScPreview::ScPreview( Window* pParent, ScDocShell* pDocSh, ScPreviewShell* pView
- bLocationValid( FALSE ),
- pLocationData( NULL ),
- pDrawView( NULL ),
-+ nCurTab ( ScDocShell::GetCurTab() ),
- bInPaint( FALSE ),
- bInGetState( FALSE ),
- pDocShell( pDocSh ),
-@@ -252,8 +253,17 @@ void ScPreview::CalcPages( SCTAB /*nToWhichTab*/ )
- // but always all sheets are used (there is no selected sheet)
- ScPrintOptions aOptions = SC_MOD()->GetPrintOptions();
-
-+ ScMarkData aMarkData;
-+ aMarkData.SelectTable( nCurTab, TRUE );
-+
- for (SCTAB i=nStart; i<nAnz; i++)
- {
-+ if (!aOptions.GetAllSheets() && !aMarkData.GetTableSelect( i )) {
-+ nPages[i] = 0;
-+ nFirstAttr[i] = 0;
-+ continue;
-+ }
-+
- long nAttrPage = i > 0 ? nFirstAttr[i-1] : 1;
-
- long nThisStart = nTotalPages;
-diff --git sc/source/ui/view/tabvwsh4.cxx sc/source/ui/view/tabvwsh4.cxx
-index 46e25c1..a7ba066 100644
---- sc/source/ui/view/tabvwsh4.cxx
-+++ sc/source/ui/view/tabvwsh4.cxx
-@@ -1194,8 +1194,13 @@ PrintDialog* __EXPORT ScTabViewShell::CreatePrintDialog( Window *pParent )
- // instead of a separate progress for each sheet from ScPrintFunc
- pDocShell->UpdatePendingRowHeights( MAXTAB, true );
-
-+ ScMarkData aMarkData;
-+ aMarkData.SelectTable( GetViewData()->GetTabNo(), TRUE );
-+
- for ( SCTAB i=0; i<nTabCount; i++ )
- {
-+ if ( !bAllTabs && !aMarkData.GetTableSelect( i ) )
-+ continue;
- ScPrintFunc aPrintFunc( pDocShell, pPrinter, i );
- nDocPageMax += aPrintFunc.GetTotalPages();
- }
diff --git sc/source/ui/view/tabvwshc.cxx sc/source/ui/view/tabvwshc.cxx
index 968984d..499c2a0 100644
--- sc/source/ui/view/tabvwshc.cxx
@@ -1134,35 +369,3 @@ index 968984d..499c2a0 100644
aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA,
GetViewData(),
-diff --git sc/source/ui/view/viewdata.cxx sc/source/ui/view/viewdata.cxx
-index df48982..e75b864 100644
---- sc/source/ui/view/viewdata.cxx
-+++ sc/source/ui/view/viewdata.cxx
-@@ -306,6 +306,7 @@ ScViewData::ScViewData( ScDocShell* pDocSh, ScTabViewShell* pViewSh )
- eRefType ( SC_REFTYPE_NONE ),
- nTabNo ( 0 ),
- nRefTabNo ( 0 ),
-+ nPasteFlags ( SC_PASTE_NONE ),
- eEditActivePart( SC_SPLIT_BOTTOMLEFT ),
- bActive ( TRUE ), //! wie initialisieren?
- bIsRefMode ( FALSE ),
-@@ -432,6 +433,7 @@ void ScViewData::InitData( ScDocument* pDocument )
- //UNUSED2008-05 aDefPageZoomX = pRef->aDefPageZoomX;
- //UNUSED2008-05 aDefPageZoomY = pRef->aDefPageZoomY;
- //UNUSED2008-05 bPagebreak = pRef->bPagebreak;
-+//UNUSED2008-05 nPasteFlags = pRef->nPasteFlags;
- //UNUSED2008-05 aLogicMode = pRef->aLogicMode;
- //UNUSED2008-05
- //UNUSED2008-05 SetGridMode ( pRef->IsGridMode() );
-diff --git sc/source/ui/view/viewfunc.cxx sc/source/ui/view/viewfunc.cxx
-index 8155a80..61670e7 100644
---- sc/source/ui/view/viewfunc.cxx
-+++ sc/source/ui/view/viewfunc.cxx
-@@ -1910,6 +1910,7 @@ void ScViewFunc::DeleteMulti( BOOL bRows, BOOL bRecord )
-
- void ScViewFunc::DeleteContents( USHORT nFlags, BOOL bRecord )
- {
-+ GetViewData()->SetPasteMode( SC_PASTE_NONE );
- // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
- BOOL bOnlyNotBecauseOfMatrix;
- BOOL bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix );
More information about the ooo-build-commit
mailing list