[Libreoffice-commits] .: 8 commits - sc/inc sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Mon Nov 14 14:27:25 PST 2011


 sc/inc/dpcachetable.hxx              |    3 
 sc/inc/dpshttab.hxx                  |    1 
 sc/inc/dptablecache.hxx              |    2 
 sc/inc/queryentry.hxx                |    4 
 sc/inc/table.hxx                     |   10 
 sc/source/core/data/dociter.cxx      |    4 
 sc/source/core/data/dpcachetable.cxx |    4 
 sc/source/core/data/dpshttab.cxx     |   10 
 sc/source/core/data/dptablecache.cxx |    4 
 sc/source/core/data/table2.cxx       |    4 
 sc/source/core/data/table3.cxx       |  770 ++++++++++++++++++-----------------
 sc/source/core/tool/queryentry.cxx   |   18 
 sc/source/core/tool/queryparam.cxx   |    2 
 13 files changed, 451 insertions(+), 385 deletions(-)

New commits:
commit e2577c3df784be265ff2314b4c25601f4f30fe04
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 14 17:26:50 2011 -0500

    This can be const.

diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index afdbed1..8d51028 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1700,7 +1700,7 @@ public:
     }
 };
 
-void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
+void lcl_PrepareQuery( const ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
 {
     bool bTopTen = false;
     SCSIZE nEntryCount = rParam.GetEntryCount();
commit d56778ac4b75517f87aaf71763c51dfdc1eb02c3
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 14 17:25:31 2011 -0500

    Prefer for_each over manual loop.

diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index f94f6b2..afdbed1 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1664,7 +1664,43 @@ void ScTable::TopTenQuery( ScQueryParam& rParam )
         DestroySortCollator();
 }
 
-static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
+namespace {
+
+class PrepareQueryItem : public std::unary_function<ScQueryEntry::Item, void>
+{
+    const ScDocument& mrDoc;
+public:
+    PrepareQueryItem(const ScDocument& rDoc) : mrDoc(rDoc) {}
+
+    void operator() (ScQueryEntry::Item& rItem)
+    {
+        // Double-check if the query by date is really appropriate.
+
+        if (rItem.meType != ScQueryEntry::ByDate)
+            return;
+
+        sal_uInt32 nIndex = 0;
+        bool bNumber = mrDoc.GetFormatTable()->
+            IsNumberFormat(rItem.maString, nIndex, rItem.mfVal);
+
+        if (bNumber && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
+        {
+            const SvNumberformat* pEntry = mrDoc.GetFormatTable()->GetEntry(nIndex);
+            if (pEntry)
+            {
+                short nNumFmtType = pEntry->GetType();
+                if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
+                    rItem.meType = ScQueryEntry::ByValue;    // not a date only
+            }
+            else
+                rItem.meType = ScQueryEntry::ByValue;    // what the ... not a date
+        }
+        else
+            rItem.meType = ScQueryEntry::ByValue;    // not a date
+    }
+};
+
+void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
 {
     bool bTopTen = false;
     SCSIZE nEntryCount = rParam.GetEntryCount();
@@ -1672,53 +1708,26 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa
     for ( SCSIZE i = 0; i < nEntryCount; ++i )
     {
         ScQueryEntry& rEntry = rParam.GetEntry(i);
-        if ( rEntry.bDoQuery )
+        if (!rEntry.bDoQuery)
+            continue;
+
+        ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+        std::for_each(rItems.begin(), rItems.end(), PrepareQueryItem(*pDoc));
+
+        if ( !bTopTen )
         {
-            ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
-            ScQueryEntry::QueryItemsType::iterator itr = rItems.begin(), itrEnd = rItems.end();
-            for (; itr != itrEnd; ++itr)
+            switch ( rEntry.eOp )
             {
-                ScQueryEntry::Item& rItem = *itr;
-                if (rItem.meType == ScQueryEntry::ByString)
+                case SC_TOPVAL:
+                case SC_BOTVAL:
+                case SC_TOPPERC:
+                case SC_BOTPERC:
                 {
-                    sal_uInt32 nIndex = 0;
-                    bool bNumber = pDoc->GetFormatTable()->
-                        IsNumberFormat(rItem.maString, nIndex, rItem.mfVal);
-                    if (rItem.meType == ScQueryEntry::ByDate)
-                    {
-                        if (bNumber && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
-                        {
-                            const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex);
-                            if (pEntry)
-                            {
-                                short nNumFmtType = pEntry->GetType();
-                                if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
-                                    rItem.meType = ScQueryEntry::ByValue;    // not a date only
-                            }
-                            else
-                                rItem.meType = ScQueryEntry::ByValue;    // what the ... not a date
-                        }
-                        else
-                            rItem.meType = ScQueryEntry::ByValue;    // not a date
-                    }
+                    bTopTen = true;
                 }
-            }
-
-            if ( !bTopTen )
-            {
-                switch ( rEntry.eOp )
+                break;
+                default:
                 {
-                    case SC_TOPVAL:
-                    case SC_BOTVAL:
-                    case SC_TOPPERC:
-                    case SC_BOTPERC:
-                    {
-                        bTopTen = true;
-                    }
-                    break;
-                    default:
-                    {
-                    }
                 }
             }
         }
@@ -1730,6 +1739,8 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa
     }
 }
 
+}
+
 SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
 {
     ScQueryParam    aParam( rParamOrg );
commit 4740d607c09025aa2a645e7578514a580dec15e5
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 14 17:15:31 2011 -0500

    Adopt lcl_PrepareQuery to multi-item queries.

diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 3538710..19adf3f 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -71,6 +71,7 @@ struct ScQueryEntry
     // creates pSearchParam and pSearchText if necessary, always RegExp!
     utl::TextSearch* GetSearchTextPtr( bool bCaseSens ) const;
 
+    QueryItemsType& GetQueryItems();
     const QueryItemsType& GetQueryItems() const;
     SC_DLLPUBLIC void SetQueryByEmpty();
     SC_DLLPUBLIC bool IsQueryByEmpty() const;
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index e1c5902..f94f6b2 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1674,29 +1674,33 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa
         ScQueryEntry& rEntry = rParam.GetEntry(i);
         if ( rEntry.bDoQuery )
         {
-            // TODO: adapt this for multi-query items.
-            ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
-            if (rItem.meType == ScQueryEntry::ByString)
+            ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+            ScQueryEntry::QueryItemsType::iterator itr = rItems.begin(), itrEnd = rItems.end();
+            for (; itr != itrEnd; ++itr)
             {
-                sal_uInt32 nIndex = 0;
-                bool bNumber = pDoc->GetFormatTable()->
-                    IsNumberFormat(rItem.maString, nIndex, rItem.mfVal);
-                if (rItem.meType == ScQueryEntry::ByDate)
+                ScQueryEntry::Item& rItem = *itr;
+                if (rItem.meType == ScQueryEntry::ByString)
                 {
-                    if (bNumber && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
+                    sal_uInt32 nIndex = 0;
+                    bool bNumber = pDoc->GetFormatTable()->
+                        IsNumberFormat(rItem.maString, nIndex, rItem.mfVal);
+                    if (rItem.meType == ScQueryEntry::ByDate)
                     {
-                        const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex);
-                        if (pEntry)
+                        if (bNumber && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
                         {
-                            short nNumFmtType = pEntry->GetType();
-                            if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
-                                rItem.meType = ScQueryEntry::ByValue;    // not a date only
+                            const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex);
+                            if (pEntry)
+                            {
+                                short nNumFmtType = pEntry->GetType();
+                                if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
+                                    rItem.meType = ScQueryEntry::ByValue;    // not a date only
+                            }
+                            else
+                                rItem.meType = ScQueryEntry::ByValue;    // what the ... not a date
                         }
                         else
-                            rItem.meType = ScQueryEntry::ByValue;    // what the ... not a date
+                            rItem.meType = ScQueryEntry::ByValue;    // not a date
                     }
-                    else
-                        rItem.meType = ScQueryEntry::ByValue;    // not a date
                 }
             }
 
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index be16cf8..47a88e7 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -91,6 +91,11 @@ ScQueryEntry& ScQueryEntry::operator=( const ScQueryEntry& r )
     return *this;
 }
 
+ScQueryEntry::QueryItemsType& ScQueryEntry::GetQueryItems()
+{
+    return maQueryItems;
+}
+
 const ScQueryEntry::QueryItemsType& ScQueryEntry::GetQueryItems() const
 {
     return maQueryItems;
commit 04fc63b20088bb704728c05d0460cf18f5f152ea
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 14 16:54:44 2011 -0500

    No more pSpecial treatment of empty / non-empty queries.

diff --git a/sc/inc/dpcachetable.hxx b/sc/inc/dpcachetable.hxx
index 9c6353d..62efc84 100644
--- a/sc/inc/dpcachetable.hxx
+++ b/sc/inc/dpcachetable.hxx
@@ -138,8 +138,7 @@ public:
 
     /** Fill the internal table from the cell range provided.  This function
         assumes that the first row is the column header. */
-    void fillTable( const ScQueryParam& rQuery, bool* pSpecial,
-        bool bIgnoreEmptyRows, bool bRepeatIfEmpty );
+    void fillTable(const ScQueryParam& rQuery, bool bIgnoreEmptyRows, bool bRepeatIfEmpty);
 
     /** Fill the internal table from database connection object.  This function
         assumes that the first row is the column header. */
diff --git a/sc/inc/dpshttab.hxx b/sc/inc/dpshttab.hxx
index 505a275..8255135 100644
--- a/sc/inc/dpshttab.hxx
+++ b/sc/inc/dpshttab.hxx
@@ -103,7 +103,6 @@ class SC_DLLPUBLIC ScSheetDPData : public ScDPTableData
 {
 private:
     ScQueryParam    aQuery;
-    bool*           pSpecial;
     bool            bIgnoreEmptyRows;
     bool            bRepeatIfEmpty;
 
diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx
index 4bfb14d..950cc54 100644
--- a/sc/inc/dptablecache.hxx
+++ b/sc/inc/dptablecache.hxx
@@ -114,7 +114,7 @@ public:
     bool IsEmptyMember( SCROW nRow, sal_uInt16 nColumn ) const;
     bool IsRowEmpty( SCROW nRow ) const;
     bool IsValid() const;
-    bool ValidQuery( SCROW nRow, const ScQueryParam& rQueryParam, bool* pSpecial ) const;
+    bool ValidQuery(SCROW nRow, const ScQueryParam& rQueryParam) const;
 
     ScDocument* GetDoc() const;//ms-cache-core
     long GetColumnCount() const;
diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 6305480..3538710 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -44,7 +44,7 @@ namespace utl {
  */
 struct ScQueryEntry
 {
-    enum QueryType { ByValue, ByString, ByDate };
+    enum QueryType { ByValue, ByString, ByDate, ByEmpty };
 
     struct Item
     {
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 041cdaa..906d306 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -758,9 +758,9 @@ public:
     void        ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 );
 
     void        Sort(const ScSortParam& rSortParam, bool bKeepQuery);
-    bool        ValidQuery(SCROW nRow, const ScQueryParam& rQueryParam,
-                    bool* pSpecial = NULL, ScBaseCell* pCell = NULL,
-                    bool* pbTestEqualCondition = NULL );
+    bool        ValidQuery(
+        SCROW nRow, const ScQueryParam& rQueryParam, ScBaseCell* pCell = NULL,
+        bool* pbTestEqualCondition = NULL);
     void        TopTenQuery( ScQueryParam& );
     SCSIZE      Query(ScQueryParam& rQueryParam, bool bKeepSub);
     bool        CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index 689e68e..f31610e 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -500,7 +500,7 @@ bool ScDBQueryDataIterator::IsQueryValid(ScDocument& rDoc, const ScQueryParam& r
 {
     if (nTab >= rDoc.GetTableCount())
         OSL_FAIL("try to access index out of bounds, FIX IT");
-    return rDoc.maTabs[nTab]->ValidQuery(nRow, rParam, NULL, pCell);
+    return rDoc.maTabs[nTab]->ValidQuery(nRow, rParam, pCell);
 }
 
 SCSIZE ScDBQueryDataIterator::SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol)
@@ -1168,7 +1168,7 @@ ScBaseCell* ScQueryCellIterator::GetThis()
             else
             {
                 bool bTestEqualCondition;
-                if ( (pDoc->maTabs[nTab])->ValidQuery( nRow, aParam, NULL,
+                if ( (pDoc->maTabs[nTab])->ValidQuery( nRow, aParam,
                         (nCol == static_cast<SCCOL>(nFirstQueryField) ? pCell : NULL),
                         (nTestEqualCondition ? &bTestEqualCondition : NULL) ) )
                 {
diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx
index 89d01df..9f3ae49 100644
--- a/sc/source/core/data/dpcachetable.cxx
+++ b/sc/source/core/data/dpcachetable.cxx
@@ -190,7 +190,7 @@ sal_Int32 ScDPCacheTable::getColSize() const
 }
 
 void ScDPCacheTable::fillTable(
-    const ScQueryParam& rQuery, bool* pSpecial, bool bIgnoreEmptyRows, bool bRepeatIfEmpty)
+    const ScQueryParam& rQuery, bool bIgnoreEmptyRows, bool bRepeatIfEmpty)
 {
     const SCROW nRowCount = getRowSize();
     const SCCOL  nColCount = (SCCOL) getColSize();
@@ -224,7 +224,7 @@ void ScDPCacheTable::fillTable(
                 }
 
                 if ( lcl_HasQueryEntry(rQuery) &&
-                    !getCache()->ValidQuery( nRow , rQuery, pSpecial ) )
+                    !getCache()->ValidQuery(nRow , rQuery) )
                     continue;
                 if ( bIgnoreEmptyRows &&  getCache()->IsRowEmpty( nRow ) )
                     continue;
diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx
index f10d62b..fdb472c 100644
--- a/sc/source/core/data/dpshttab.cxx
+++ b/sc/source/core/data/dpshttab.cxx
@@ -63,21 +63,18 @@ using ::std::vector;
 ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, const ScDPCache* pCache) :
     ScDPTableData(pD),
     aQuery ( rDesc.GetQueryParam() ),
-    pSpecial(NULL),
     bIgnoreEmptyRows( false ),
     bRepeatIfEmpty(false),
     mrDesc(rDesc),
     aCacheTable(pCache)
 {
     SCSIZE nEntryCount( aQuery.GetEntryCount());
-    pSpecial = new bool[nEntryCount];
     for (SCSIZE j = 0; j < nEntryCount; ++j)
     {
         ScQueryEntry& rEntry = aQuery.GetEntry(j);
         if (rEntry.bDoQuery)
         {
             ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
-            pSpecial[j] = false;
             if (rItem.meType == ScQueryEntry::ByString)
             {
                 sal_uInt32 nIndex = 0;
@@ -85,17 +82,12 @@ ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, con
                     rItem.maString, nIndex, rItem.mfVal);
                 rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
             }
-            else if (rEntry.IsQueryByEmpty() || rEntry.IsQueryByNonEmpty())
-            {
-                pSpecial[j] = true;
-            }
         }
     }
 }
 
 ScSheetDPData::~ScSheetDPData()
 {
-     delete[] pSpecial;
 }
 
 void ScSheetDPData::DisposeData()
@@ -203,7 +195,7 @@ void ScSheetDPData::CreateCacheTable()
     if (!aCacheTable.hasCache())
         aCacheTable.setCache(mrDesc.CreateCache());
 
-    aCacheTable.fillTable(aQuery, pSpecial, bIgnoreEmptyRows, bRepeatIfEmpty);
+    aCacheTable.fillTable(aQuery, bIgnoreEmptyRows, bRepeatIfEmpty);
 }
 
 void ScSheetDPData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rCatDims)
diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx
index 0ebf847..0ab7334 100644
--- a/sc/source/core/data/dptablecache.cxx
+++ b/sc/source/core/data/dptablecache.cxx
@@ -576,7 +576,7 @@ sal_uLong ScDPCache::GetDimNumType( SCCOL nDim) const
         return GetNumType(maTableDataValues[nDim][0].nNumFormat);
 }
 
-bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpecial) const
+bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam) const
 {
     if (!rParam.GetEntry(0).bDoQuery)
         return true;
@@ -616,7 +616,7 @@ bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpeci
         bool bOk = false;
         bool bTestEqual = false;
 
-        if (pSpecial && pSpecial[i])
+        if (rEntry.GetQueryItem().meType == ScQueryEntry::ByEmpty)
         {
             if (rEntry.IsQueryByEmpty())
                 bOk = !pCellData->IsHasData();
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index f9bab9a..e1c5902 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1441,9 +1441,9 @@ public:
 
 }
 
-bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
-        bool* pSpecial /* =NULL */ , ScBaseCell* pCell /* =NULL */ ,
-        bool* pbTestEqualCondition /* = NULL */ )
+bool ScTable::ValidQuery(
+    SCROW nRow, const ScQueryParam& rParam, ScBaseCell* pCell,
+    bool* pbTestEqualCondition)
 {
     if (!rParam.GetEntry(0).bDoQuery)
         return true;
@@ -1468,7 +1468,8 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
 
         std::pair<bool,bool> aRes(false, false);
 
-        if ( pSpecial && pSpecial[i] )
+        const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+        if (rItems.size() == 1 && rItems.front().meType == ScQueryEntry::ByEmpty)
         {
             if (rEntry.IsQueryByEmpty())
                 aRes.first = !aCol[rEntry.nField].HasDataAt(nRow);
@@ -1480,7 +1481,6 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
         }
         else
         {
-            const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
             ScQueryEntry::QueryItemsType::const_iterator itr = rItems.begin(), itrEnd = rItems.end();
 
             for (; itr != itrEnd; ++itr)
@@ -1664,14 +1664,13 @@ void ScTable::TopTenQuery( ScQueryParam& rParam )
         DestroySortCollator();
 }
 
-static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam, bool* pSpecial )
+static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam )
 {
     bool bTopTen = false;
     SCSIZE nEntryCount = rParam.GetEntryCount();
 
     for ( SCSIZE i = 0; i < nEntryCount; ++i )
     {
-        pSpecial[i] = false;
         ScQueryEntry& rEntry = rParam.GetEntry(i);
         if ( rEntry.bDoQuery )
         {
@@ -1700,14 +1699,7 @@ static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rPa
                         rItem.meType = ScQueryEntry::ByValue;    // not a date
                 }
             }
-            else
-            {
-                // call from UNO or second call from autofilter
-                if (rEntry.IsQueryByEmpty() || rEntry.IsQueryByNonEmpty())
-                {
-                    pSpecial[i] = true;
-                }
-            }
+
             if ( !bTopTen )
             {
                 switch ( rEntry.eOp )
@@ -1749,9 +1741,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
     SCROW nOutRow   = 0;
     SCROW nHeader   = aParam.bHasHeader ? 1 : 0;
 
-    SCSIZE nEntryCount = aParam.GetEntryCount();
-    bool* pSpecial = new bool[nEntryCount];
-    lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
+    lcl_PrepareQuery(pDocument, this, aParam);
 
     if (!aParam.bInplace)
     {
@@ -1769,7 +1759,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
     for (SCROW j = aParam.nRow1 + nHeader; j <= nRealRow2; ++j)
     {
         bool bResult;                                   // Filterergebnis
-        bool bValid = ValidQuery(j, aParam, pSpecial);
+        bool bValid = ValidQuery(j, aParam);
         if (!bValid && bKeepSub)                        // Subtotals stehenlassen
         {
             for (SCCOL nCol=aParam.nCol1; nCol<=aParam.nCol2 && !bValid; nCol++)
@@ -1845,7 +1835,6 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
     if (aParam.bInplace)
         SetDrawPageSize();
 
-    delete[] pSpecial;
     return nCount;
 }
 
@@ -2113,12 +2102,11 @@ void ScTable::GetFilteredFilterEntries(
     }
     nEntryCount = aParam.GetEntryCount();
 
-    bool* pSpecial = new bool[nEntryCount];
-    lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
+    lcl_PrepareQuery(pDocument, this, aParam);
     bool bHasDates = false;
     for ( SCROW j = nRow1; j <= nRow2; ++j )
     {
-        if ( ValidQuery( j, aParam, pSpecial ) )
+        if (ValidQuery(j, aParam))
         {
             bool bThisHasDates = false;
             aCol[nCol].GetFilterEntries( j, j, rStrings, bThisHasDates );
@@ -2127,7 +2115,6 @@ void ScTable::GetFilteredFilterEntries(
     }
 
     rHasDates = bHasDates;
-    delete[] pSpecial;
 }
 
 bool ScTable::GetDataEntries(SCCOL nCol, SCROW nRow, TypedScStrCollection& rStrings, bool bLimit)
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index c58f37f..be16cf8 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -100,7 +100,7 @@ void ScQueryEntry::SetQueryByEmpty()
 {
     eOp = SC_EQUAL;
     Item& rItem = GetQueryItem();
-    rItem.meType = ByValue;
+    rItem.meType = ByEmpty;
     rItem.maString = rtl::OUString();
     rItem.mfVal = SC_EMPTYFIELDS;
 }
@@ -113,7 +113,7 @@ bool ScQueryEntry::IsQueryByEmpty() const
 
     const Item& rItem = GetQueryItem();
     return eOp == SC_EQUAL &&
-        rItem.meType == ByValue &&
+        rItem.meType == ByEmpty &&
         rItem.maString.isEmpty() &&
         rItem.mfVal == SC_EMPTYFIELDS;
 }
@@ -122,7 +122,7 @@ void ScQueryEntry::SetQueryByNonEmpty()
 {
     eOp = SC_EQUAL;
     Item& rItem = GetQueryItem();
-    rItem.meType = ByValue;
+    rItem.meType = ByEmpty;
     rItem.maString = rtl::OUString();
     rItem.mfVal = SC_NONEMPTYFIELDS;
 }
@@ -135,7 +135,7 @@ bool ScQueryEntry::IsQueryByNonEmpty() const
 
     const Item& rItem = GetQueryItem();
     return eOp == SC_EQUAL &&
-        rItem.meType == ByValue &&
+        rItem.meType == ByEmpty &&
         rItem.maString.isEmpty() &&
         rItem.mfVal == SC_NONEMPTYFIELDS;
 }
diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx
index a1df6a2..d4ead74 100644
--- a/sc/source/core/tool/queryparam.cxx
+++ b/sc/source/core/tool/queryparam.cxx
@@ -264,7 +264,7 @@ ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
     bByRow      = r.bByRow;
     bDestPers   = r.bDestPers;
 
-    maEntries = r.maEntries;
+    maEntries = r.maEntries.clone();
 
     return *this;
 }
commit f6d50b0ebb08ccdeae2d62ad070145a28ce732f8
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 14 16:00:30 2011 -0500

    Make multi-item query possible.

diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 6419141..6305480 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -71,6 +71,7 @@ struct ScQueryEntry
     // creates pSearchParam and pSearchText if necessary, always RegExp!
     utl::TextSearch* GetSearchTextPtr( bool bCaseSens ) const;
 
+    const QueryItemsType& GetQueryItems() const;
     SC_DLLPUBLIC void SetQueryByEmpty();
     SC_DLLPUBLIC bool IsQueryByEmpty() const;
     SC_DLLPUBLIC void SetQueryByNonEmpty();
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index f2846ee..f9bab9a 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1468,10 +1468,6 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
 
         std::pair<bool,bool> aRes(false, false);
 
-        // For now, we only handle single item queries.  We need to adopt this
-        // to multi-item queries later.
-        const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
-
         if ( pSpecial && pSpecial[i] )
         {
             if (rEntry.IsQueryByEmpty())
@@ -1482,13 +1478,31 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
                 aRes.first = aCol[rEntry.nField].HasDataAt(nRow);
             }
         }
-        else if (aEval.isQueryByValue(rItem, nCol, nRow, pCell))
-        {
-            aRes = aEval.compareByValue(pCell, nCol, nRow, rEntry, rItem);
-        }
-        else if (aEval.isQueryByString(rEntry, rItem, nCol, nRow, pCell))
+        else
         {
-            aRes = aEval.compareByString(pCell, nRow, rEntry, rItem);
+            const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+            ScQueryEntry::QueryItemsType::const_iterator itr = rItems.begin(), itrEnd = rItems.end();
+
+            for (; itr != itrEnd; ++itr)
+            {
+                if (aEval.isQueryByValue(*itr, nCol, nRow, pCell))
+                {
+                    std::pair<bool,bool> aThisRes =
+                        aEval.compareByValue(pCell, nCol, nRow, rEntry, *itr);
+                    aRes.first |= aThisRes.first;
+                    aRes.second |= aThisRes.second;
+                }
+                else if (aEval.isQueryByString(rEntry, *itr, nCol, nRow, pCell))
+                {
+                    std::pair<bool,bool> aThisRes =
+                        aEval.compareByString(pCell, nRow, rEntry, *itr);
+                    aRes.first |= aThisRes.first;
+                    aRes.second |= aThisRes.second;
+                }
+
+                if (aRes.first && aRes.second)
+                    break;
+            }
         }
 
         if (nPos == -1)
diff --git a/sc/source/core/tool/queryentry.cxx b/sc/source/core/tool/queryentry.cxx
index 7ea2c49..c58f37f 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -91,6 +91,11 @@ ScQueryEntry& ScQueryEntry::operator=( const ScQueryEntry& r )
     return *this;
 }
 
+const ScQueryEntry::QueryItemsType& ScQueryEntry::GetQueryItems() const
+{
+    return maQueryItems;
+}
+
 void ScQueryEntry::SetQueryByEmpty()
 {
     eOp = SC_EQUAL;
commit 625025f6c24a96fa899ad1d9b493dfd73f2755c9
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 14 15:35:02 2011 -0500

    Aggregate all these local functions into a class.
    
    This also reduces the number of parameters in each function.

diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index a7604dd..f2846ee 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1067,348 +1067,377 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
 
 namespace {
 
-bool isQueryByValue(
-    const ScTable& rTable, const ScQueryEntry::Item& rItem,
-    SCCOL nCol, SCROW nRow, const ScBaseCell* pCell)
+class QueryEvaluator
 {
-    if (rItem.meType == ScQueryEntry::ByString)
-        return false;
-
-    if (pCell)
-        return pCell->HasValueData();
-
-    return rTable.HasValueData(nCol, nRow);
-}
-
-std::pair<bool,bool> compareByValue(
-    const ScDocument& rDoc, const ScTable& rTab, const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
-    const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool* pbTestEqualCondition)
-{
-    bool bOk = false;
-    bool bTestEqual = false;
-    double nCellVal;
-    if ( pCell )
+    const ScDocument& mrDoc;
+    const ScTable& mrTab;
+    const ScQueryParam& mrParam;
+    const bool* mpTestEqualCondition;
+    utl::TransliterationWrapper* mpTransliteration;
+    CollatorWrapper* mpCollator;
+    const bool mbMatchWholeCell;
+
+    bool isPartialTextMatchOp(const ScQueryEntry& rEntry) const
     {
-        switch ( pCell->GetCellType() )
+        switch (rEntry.eOp)
         {
-            case CELLTYPE_VALUE :
-                nCellVal = ((ScValueCell*)pCell)->GetValue();
-            break;
-            case CELLTYPE_FORMULA :
-                nCellVal = ((ScFormulaCell*)pCell)->GetValue();
-            break;
+            // these operators can only be used with textural comparisons.
+            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:
-                nCellVal = 0.0;
-        }
-
-    }
-    else
-        nCellVal = rTab.GetValue(nCol, nRow);
-
-    /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
-     * date+time format was queried rEntry.bQueryByDate is not set. In
-     * case other queries wanted to use this mechanism they should do
-     * the same, in other words only if rEntry.nVal is an integer value
-     * rEntry.bQueryByDate should be true and the time fraction be
-     * stripped here. */
-    if (rItem.meType == ScQueryEntry::ByDate)
-    {
-        sal_uInt32 nNumFmt = rTab.GetNumberFormat(nCol, nRow);
-        const SvNumberformat* pEntry = rDoc.GetFormatTable()->GetEntry(nNumFmt);
-        if (pEntry)
-        {
-            short nNumFmtType = pEntry->GetType();
-            /* NOTE: Omitting the check for absence of
-             * NUMBERFORMAT_TIME would include also date+time formatted
-             * values of the same day. That may be desired in some
-             * cases, querying all time values of a day, but confusing
-             * in other cases. A user can always setup a standard
-             * filter query for x >= date AND x < date+1 */
-            if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
-            {
-                // The format is of date type.  Strip off the time
-                // element.
-                nCellVal = ::rtl::math::approxFloor(nCellVal);
-            }
+                ;
         }
+        return false;
     }
 
-    switch (rEntry.eOp)
+    bool isTextMatchOp(const ScQueryEntry& rEntry) const
     {
-        case SC_EQUAL :
-            bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-            break;
-        case SC_LESS :
-            bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-            break;
-        case SC_GREATER :
-            bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-            break;
-        case SC_LESS_EQUAL :
-            bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-            if ( bOk && pbTestEqualCondition )
-                bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-            break;
-        case SC_GREATER_EQUAL :
-            bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual( nCellVal, rItem.mfVal);
-            if ( bOk && pbTestEqualCondition )
-                bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-            break;
-        case SC_NOT_EQUAL :
-            bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-            break;
-        default:
+        if (isPartialTextMatchOp(rEntry))
+            return true;
+
+        switch (rEntry.eOp)
         {
-            // added to avoid warnings
+            // these operators can be used for either textural or value comparison.
+            case SC_EQUAL:
+            case SC_NOT_EQUAL:
+                return true;
+            default:
+                ;
         }
+        return false;
     }
 
-    return std::pair<bool,bool>(bOk, bTestEqual);
-}
-
-bool isPartialTextMatchOp(const ScQueryEntry& rEntry)
-{
-    switch (rEntry.eOp)
+    bool isRealRegExp(const ScQueryEntry& rEntry) const
     {
-        // these operators can only be used with textural comparisons.
-        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:
-            ;
-    }
-    return false;
-}
-
-bool isTextMatchOp(const ScQueryEntry& rEntry)
-{
-    if (isPartialTextMatchOp(rEntry))
-        return true;
+        if (!mrParam.bRegExp)
+            return false;
 
-    switch (rEntry.eOp)
-    {
-        // these operators can be used for either textural or value comparison.
-        case SC_EQUAL:
-        case SC_NOT_EQUAL:
-            return true;
-        default:
-            ;
+        return isTextMatchOp(rEntry);
     }
-    return false;
-}
 
-bool isQueryByString(
-    const ScTable& rTable, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem,
-    SCCOL nCol, SCROW nRow, const ScBaseCell* pCell)
-{
-    if (isTextMatchOp(rEntry))
-        return true;
+    bool isTestRegExp(const ScQueryEntry& rEntry) const
+    {
+        if (!mpTestEqualCondition)
+            return false;
 
-    if (rItem.meType != ScQueryEntry::ByString)
-        return false;
+        if (!mrParam.bRegExp)
+            return false;
 
-    if (pCell)
-        return pCell->HasStringData();
+        return (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL);
+    }
 
-    return rTable.HasStringData(nCol, nRow);
-}
+public:
+    QueryEvaluator(const ScDocument& rDoc, const ScTable& rTab, const ScQueryParam& rParam,
+                   const bool* pTestEqualCondition) :
+        mrDoc(rDoc),
+        mrTab(rTab),
+        mrParam(rParam),
+        mpTestEqualCondition(pTestEqualCondition),
+        mbMatchWholeCell(rDoc.GetDocOptions().IsMatchWholeCell())
+    {
+        if (rParam.bCaseSens)
+        {
+            mpTransliteration = ScGlobal::GetCaseTransliteration();
+            mpCollator = ScGlobal::GetCaseCollator();
+        }
+        else
+        {
+            mpTransliteration = ScGlobal::GetpTransliteration();
+            mpCollator = ScGlobal::GetCollator();
+        }
+    }
 
-bool isRealRegExp(const ScQueryParam& rParam, const ScQueryEntry& rEntry)
-{
-    if (!rParam.bRegExp)
-        return false;
+    bool isQueryByValue(
+        const ScQueryEntry::Item& rItem, SCCOL nCol, SCROW nRow, const ScBaseCell* pCell)
+    {
+        if (rItem.meType == ScQueryEntry::ByString)
+            return false;
 
-    return isTextMatchOp(rEntry);
-}
+        if (pCell)
+            return pCell->HasValueData();
 
-bool isTestRegExp(const ScQueryParam& rParam, const ScQueryEntry& rEntry, bool* pbTestEqualCondition)
-{
-    if (!pbTestEqualCondition)
-        return false;
+        return mrTab.HasValueData(nCol, nRow);
+    }
 
-    if (!rParam.bRegExp)
-        return false;
+    bool isQueryByString(
+        const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem,
+        SCCOL nCol, SCROW nRow, const ScBaseCell* pCell)
+    {
+        if (isTextMatchOp(rEntry))
+            return true;
 
-    return (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL);
-}
+        if (rItem.meType != ScQueryEntry::ByString)
+            return false;
 
-std::pair<bool,bool> compareByString(
-    const ScDocument& rDoc, const ScTable& rTab, ScBaseCell* pCell, SCROW nRow,
-    const ScQueryParam& rParam, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool bMatchWholeCell,
-    ::utl::TransliterationWrapper* pTransliteration, CollatorWrapper* pCollator,
-    bool* pbTestEqualCondition)
-{
-    bool bOk = false;
-    bool bTestEqual = false;
-    rtl::OUString  aCellStr;
-    if (isPartialTextMatchOp(rEntry))
-        // may have to do partial textural comparison.
-        bMatchWholeCell = false;
+        if (pCell)
+            return pCell->HasStringData();
 
-    if ( pCell )
-    {
-        if (pCell->GetCellType() != CELLTYPE_NOTE)
-        {
-            sal_uLong nFormat = rTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
-            ScCellFormat::GetInputString(pCell, nFormat, aCellStr, *rDoc.GetFormatTable());
-        }
+        return mrTab.HasStringData(nCol, nRow);
     }
-    else
-        rTab.GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
-
-    bool bRealRegExp = isRealRegExp(rParam, rEntry);
-    bool bTestRegExp = isTestRegExp(rParam, rEntry, pbTestEqualCondition);
 
-    if ( bRealRegExp || bTestRegExp )
+    std::pair<bool,bool> compareByValue(
+        const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
+        const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem)
     {
-        xub_StrLen nStart = 0;
-        xub_StrLen nEnd   = aCellStr.getLength();
-
-        // from 614 on, nEnd is behind the found text
-        bool bMatch = false;
-        if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
+        bool bOk = false;
+        bool bTestEqual = false;
+        double nCellVal;
+        if ( pCell )
         {
-            nEnd = 0;
-            nStart = aCellStr.getLength();
-            bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
-                ->SearchBkwrd( aCellStr, &nStart, &nEnd );
+            switch ( pCell->GetCellType() )
+            {
+                case CELLTYPE_VALUE :
+                    nCellVal = ((ScValueCell*)pCell)->GetValue();
+                break;
+                case CELLTYPE_FORMULA :
+                    nCellVal = ((ScFormulaCell*)pCell)->GetValue();
+                break;
+                default:
+                    nCellVal = 0.0;
+            }
+
         }
         else
+            nCellVal = mrTab.GetValue(nCol, nRow);
+
+        /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
+         * date+time format was queried rEntry.bQueryByDate is not set. In
+         * case other queries wanted to use this mechanism they should do
+         * the same, in other words only if rEntry.nVal is an integer value
+         * rEntry.bQueryByDate should be true and the time fraction be
+         * stripped here. */
+        if (rItem.meType == ScQueryEntry::ByDate)
         {
-            bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
-                ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+            sal_uInt32 nNumFmt = mrTab.GetNumberFormat(nCol, nRow);
+            const SvNumberformat* pEntry = mrDoc.GetFormatTable()->GetEntry(nNumFmt);
+            if (pEntry)
+            {
+                short nNumFmtType = pEntry->GetType();
+                /* NOTE: Omitting the check for absence of
+                 * NUMBERFORMAT_TIME would include also date+time formatted
+                 * values of the same day. That may be desired in some
+                 * cases, querying all time values of a day, but confusing
+                 * in other cases. A user can always setup a standard
+                 * filter query for x >= date AND x < date+1 */
+                if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
+                {
+                    // The format is of date type.  Strip off the time
+                    // element.
+                    nCellVal = ::rtl::math::approxFloor(nCellVal);
+                }
+            }
         }
-        if ( bMatch && bMatchWholeCell
-                && (nStart != 0 || nEnd != aCellStr.getLength()) )
-            bMatch = false;    // RegExp must match entire cell string
-        if ( bRealRegExp )
-            switch (rEntry.eOp)
+
+        switch (rEntry.eOp)
         {
-            case SC_EQUAL:
-            case SC_CONTAINS:
-                bOk = bMatch;
+            case SC_EQUAL :
+                bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
                 break;
-            case SC_NOT_EQUAL:
-            case SC_DOES_NOT_CONTAIN:
-                bOk = !bMatch;
+            case SC_LESS :
+                bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
                 break;
-            case SC_BEGINS_WITH:
-                bOk = ( bMatch && (nStart == 0) );
+            case SC_GREATER :
+                bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
                 break;
-            case SC_DOES_NOT_BEGIN_WITH:
-                bOk = !( bMatch && (nStart == 0) );
+            case SC_LESS_EQUAL :
+                bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+                if ( bOk && mpTestEqualCondition )
+                    bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
                 break;
-            case SC_ENDS_WITH:
-                bOk = ( bMatch && (nEnd == aCellStr.getLength()) );
+            case SC_GREATER_EQUAL :
+                bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual( nCellVal, rItem.mfVal);
+                if ( bOk && mpTestEqualCondition )
+                    bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
                 break;
-            case SC_DOES_NOT_END_WITH:
-                bOk = !( bMatch && (nEnd == aCellStr.getLength()) );
+            case SC_NOT_EQUAL :
+                bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
                 break;
             default:
-                {
-                    // added to avoid warnings
-                }
+            {
+                // added to avoid warnings
+            }
         }
-        else
-            bTestEqual = bMatch;
+
+        return std::pair<bool,bool>(bOk, bTestEqual);
     }
-    if ( !bRealRegExp )
+
+    std::pair<bool,bool> compareByString(
+        ScBaseCell* pCell, SCROW nRow, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem)
     {
-        // Simple string matching i.e. no regexp match.
-        if (isTextMatchOp(rEntry))
+        bool bOk = false;
+        bool bTestEqual = false;
+        bool bMatchWholeCell = mbMatchWholeCell;
+        rtl::OUString  aCellStr;
+        if (isPartialTextMatchOp(rEntry))
+            // may have to do partial textural comparison.
+            bMatchWholeCell = false;
+
+        if ( pCell )
         {
-            if (!rItem.meType != ScQueryEntry::ByString && rItem.maString.isEmpty())
+            if (pCell->GetCellType() != CELLTYPE_NOTE)
             {
-                // #i18374# When used from functions (match, countif, sumif, vlookup, hlookup, lookup),
-                // the query value is assigned directly, and the string is empty. In that case,
-                // don't find any string (isEqual would find empty string results in formula cells).
-                bOk = false;
-                if ( rEntry.eOp == SC_NOT_EQUAL )
-                    bOk = !bOk;
+                sal_uLong nFormat = mrTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
+                ScCellFormat::GetInputString(pCell, nFormat, aCellStr, *mrDoc.GetFormatTable());
             }
-            else if ( bMatchWholeCell )
+        }
+        else
+            mrTab.GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
+
+        bool bRealRegExp = isRealRegExp(rEntry);
+        bool bTestRegExp = isTestRegExp(rEntry);
+
+        if ( bRealRegExp || bTestRegExp )
+        {
+            xub_StrLen nStart = 0;
+            xub_StrLen nEnd   = aCellStr.getLength();
+
+            // from 614 on, nEnd is behind the found text
+            bool bMatch = false;
+            if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
             {
-                bOk = pTransliteration->isEqual(aCellStr, rEntry.GetQueryItem().maString);
-                if ( rEntry.eOp == SC_NOT_EQUAL )
-                    bOk = !bOk;
+                nEnd = 0;
+                nStart = aCellStr.getLength();
+                bMatch = (bool) rEntry.GetSearchTextPtr( mrParam.bCaseSens )
+                    ->SearchBkwrd( aCellStr, &nStart, &nEnd );
             }
             else
             {
-                const rtl::OUString& rQueryStr = rItem.maString;
-                String aCell( pTransliteration->transliterate(
-                    aCellStr, ScGlobal::eLnge, 0, aCellStr.getLength(),
-                    NULL ) );
-                String aQuer( pTransliteration->transliterate(
-                    rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(),
-                    NULL ) );
-                xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
-                    || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
-                xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
+                bMatch = (bool) rEntry.GetSearchTextPtr( mrParam.bCaseSens )
+                    ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+            }
+            if ( bMatch && bMatchWholeCell
+                    && (nStart != 0 || nEnd != aCellStr.getLength()) )
+                bMatch = false;    // RegExp must match entire cell string
+            if ( bRealRegExp )
                 switch (rEntry.eOp)
-                {
+            {
                 case SC_EQUAL:
                 case SC_CONTAINS:
-                    bOk = ( nStrPos != STRING_NOTFOUND );
+                    bOk = bMatch;
                     break;
                 case SC_NOT_EQUAL:
                 case SC_DOES_NOT_CONTAIN:
-                    bOk = ( nStrPos == STRING_NOTFOUND );
+                    bOk = !bMatch;
                     break;
                 case SC_BEGINS_WITH:
-                    bOk = ( nStrPos == 0 );
+                    bOk = ( bMatch && (nStart == 0) );
                     break;
                 case SC_DOES_NOT_BEGIN_WITH:
-                    bOk = ( nStrPos != 0 );
+                    bOk = !( bMatch && (nStart == 0) );
                     break;
                 case SC_ENDS_WITH:
-                    bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
+                    bOk = ( bMatch && (nEnd == aCellStr.getLength()) );
                     break;
                 case SC_DOES_NOT_END_WITH:
-                    bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
+                    bOk = !( bMatch && (nEnd == aCellStr.getLength()) );
                     break;
                 default:
                     {
                         // added to avoid warnings
                     }
-                }
             }
+            else
+                bTestEqual = bMatch;
         }
-        else
-        {   // use collator here because data was probably sorted
-            sal_Int32 nCompare = pCollator->compareString(
-                aCellStr, rEntry.GetQueryItem().maString);
-            switch (rEntry.eOp)
+        if ( !bRealRegExp )
+        {
+            // Simple string matching i.e. no regexp match.
+            if (isTextMatchOp(rEntry))
             {
-                case SC_LESS :
-                    bOk = (nCompare < 0);
-                    break;
-                case SC_GREATER :
-                    bOk = (nCompare > 0);
-                    break;
-                case SC_LESS_EQUAL :
-                    bOk = (nCompare <= 0);
-                    if ( bOk && pbTestEqualCondition && !bTestEqual )
-                        bTestEqual = (nCompare == 0);
-                    break;
-                case SC_GREATER_EQUAL :
-                    bOk = (nCompare >= 0);
-                    if ( bOk && pbTestEqualCondition && !bTestEqual )
-                        bTestEqual = (nCompare == 0);
-                    break;
-                default:
+                if (!rItem.meType != ScQueryEntry::ByString && rItem.maString.isEmpty())
+                {
+                    // #i18374# When used from functions (match, countif, sumif, vlookup, hlookup, lookup),
+                    // the query value is assigned directly, and the string is empty. In that case,
+                    // don't find any string (isEqual would find empty string results in formula cells).
+                    bOk = false;
+                    if ( rEntry.eOp == SC_NOT_EQUAL )
+                        bOk = !bOk;
+                }
+                else if ( bMatchWholeCell )
                 {
-                    // added to avoid warnings
+                    bOk = mpTransliteration->isEqual(aCellStr, rEntry.GetQueryItem().maString);
+                    if ( rEntry.eOp == SC_NOT_EQUAL )
+                        bOk = !bOk;
+                }
+                else
+                {
+                    const rtl::OUString& rQueryStr = rItem.maString;
+                    String aCell( mpTransliteration->transliterate(
+                        aCellStr, ScGlobal::eLnge, 0, aCellStr.getLength(),
+                        NULL ) );
+                    String aQuer( mpTransliteration->transliterate(
+                        rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(),
+                        NULL ) );
+                    xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
+                        || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
+                    xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
+                    switch (rEntry.eOp)
+                    {
+                    case SC_EQUAL:
+                    case SC_CONTAINS:
+                        bOk = ( nStrPos != STRING_NOTFOUND );
+                        break;
+                    case SC_NOT_EQUAL:
+                    case SC_DOES_NOT_CONTAIN:
+                        bOk = ( nStrPos == STRING_NOTFOUND );
+                        break;
+                    case SC_BEGINS_WITH:
+                        bOk = ( nStrPos == 0 );
+                        break;
+                    case SC_DOES_NOT_BEGIN_WITH:
+                        bOk = ( nStrPos != 0 );
+                        break;
+                    case SC_ENDS_WITH:
+                        bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
+                        break;
+                    case SC_DOES_NOT_END_WITH:
+                        bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
+                        break;
+                    default:
+                        {
+                            // added to avoid warnings
+                        }
+                    }
+                }
+            }
+            else
+            {   // use collator here because data was probably sorted
+                sal_Int32 nCompare = mpCollator->compareString(
+                    aCellStr, rEntry.GetQueryItem().maString);
+                switch (rEntry.eOp)
+                {
+                    case SC_LESS :
+                        bOk = (nCompare < 0);
+                        break;
+                    case SC_GREATER :
+                        bOk = (nCompare > 0);
+                        break;
+                    case SC_LESS_EQUAL :
+                        bOk = (nCompare <= 0);
+                        if ( bOk && mpTestEqualCondition && !bTestEqual )
+                            bTestEqual = (nCompare == 0);
+                        break;
+                    case SC_GREATER_EQUAL :
+                        bOk = (nCompare >= 0);
+                        if ( bOk && mpTestEqualCondition && !bTestEqual )
+                            bTestEqual = (nCompare == 0);
+                        break;
+                    default:
+                    {
+                        // added to avoid warnings
+                    }
                 }
             }
         }
-    }
 
-    return std::pair<bool,bool>(bOk, bTestEqual);
-}
+        return std::pair<bool,bool>(bOk, bTestEqual);
+    }
+};
 
 }
 
@@ -1426,11 +1455,7 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
     std::vector<bool> aTestEqual(nEntryCount, false);
 
     long    nPos = -1;
-    bool    bMatchWholeCell = pDocument->GetDocOptions().IsMatchWholeCell();
-    CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() :
-        ScGlobal::GetCollator());
-    ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ?
-        ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration());
+    QueryEvaluator aEval(*pDocument, *this, rParam, pbTestEqualCondition);
 
     for (size_t i = 0; i < nEntryCount && rParam.GetEntry(i).bDoQuery; ++i)
     {
@@ -1441,8 +1466,7 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
         if ( !pCell || i > 0 )
             pCell = GetCell(nCol, nRow);
 
-        bool bOk = false;
-        bool bTestEqual = false;
+        std::pair<bool,bool> aRes(false, false);
 
         // For now, we only handle single item queries.  We need to adopt this
         // to multi-item queries later.
@@ -1451,47 +1475,40 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
         if ( pSpecial && pSpecial[i] )
         {
             if (rEntry.IsQueryByEmpty())
-                bOk = !( aCol[rEntry.nField].HasDataAt( nRow ) );
+                aRes.first = !aCol[rEntry.nField].HasDataAt(nRow);
             else
             {
                 OSL_ASSERT(rEntry.IsQueryByNonEmpty());
-                bOk = aCol[rEntry.nField].HasDataAt( nRow );
+                aRes.first = aCol[rEntry.nField].HasDataAt(nRow);
             }
         }
-        else if (isQueryByValue(*this, rItem, nCol, nRow, pCell))
+        else if (aEval.isQueryByValue(rItem, nCol, nRow, pCell))
         {
-            std::pair<bool,bool> res = compareByValue(
-                *pDocument, *this, pCell, nCol, nRow, rEntry, rItem, pbTestEqualCondition);
-            bOk = res.first;
-            bTestEqual = res.second;
+            aRes = aEval.compareByValue(pCell, nCol, nRow, rEntry, rItem);
         }
-        else if (isQueryByString(*this, rEntry, rItem, nCol, nRow, pCell))
+        else if (aEval.isQueryByString(rEntry, rItem, nCol, nRow, pCell))
         {
-            std::pair<bool,bool> res = compareByString(
-                *pDocument, *this, pCell, nRow, rParam, rEntry, rItem, bMatchWholeCell,
-                pTransliteration, pCollator, pbTestEqualCondition);
-            bOk = res.first;
-            bTestEqual = res.second;
+            aRes = aEval.compareByString(pCell, nRow, rEntry, rItem);
         }
 
         if (nPos == -1)
         {
             nPos++;
-            aPassed[nPos] = bOk;
-            aTestEqual[nPos] = bTestEqual;
+            aPassed[nPos] = aRes.first;
+            aTestEqual[nPos] = aRes.second;
         }
         else
         {
             if (rEntry.eConnect == SC_AND)
             {
-                aPassed[nPos] = aPassed[nPos] && bOk;
-                aTestEqual[nPos] = aTestEqual[nPos] && bTestEqual;
+                aPassed[nPos] = aPassed[nPos] && aRes.first;
+                aTestEqual[nPos] = aTestEqual[nPos] && aRes.second;
             }
             else
             {
                 nPos++;
-                aPassed[nPos] = bOk;
-                aTestEqual[nPos] = bTestEqual;
+                aPassed[nPos] = aRes.first;
+                aTestEqual[nPos] = aRes.second;
             }
         }
     }
commit 3b58e5871f6da7be54dad5c1da1c0f0a8378ad73
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 14 15:04:41 2011 -0500

    Marking methods const where possible.

diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index c7f0617..041cdaa 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -312,14 +312,14 @@ public:
     void        SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError);
 
     void        GetString( SCCOL nCol, SCROW nRow, rtl::OUString& rString );
-    void        GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString );
+    void        GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const;
     double      GetValue( const ScAddress& rPos ) const
                     {
                         return ValidColRow(rPos.Col(),rPos.Row()) ?
                             aCol[rPos.Col()].GetValue( rPos.Row() ) :
                             0.0;
                     }
-    double      GetValue( SCCOL nCol, SCROW nRow );
+    double      GetValue( SCCOL nCol, SCROW nRow ) const;
     void        GetFormula( SCCOL nCol, SCROW nRow, rtl::OUString& rFormula );
 
     CellType    GetCellType( const ScAddress& rPos ) const
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 73c26ba..af10a16 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1067,7 +1067,7 @@ void ScTable::GetString( SCCOL nCol, SCROW nRow, rtl::OUString& rString )
 }
 
 
-void ScTable::GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString )
+void ScTable::GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const
 {
     if (ValidColRow(nCol,nRow))
         aCol[nCol].GetInputString( nRow, rString );
@@ -1076,7 +1076,7 @@ void ScTable::GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString )
 }
 
 
-double ScTable::GetValue( SCCOL nCol, SCROW nRow )
+double ScTable::GetValue( SCCOL nCol, SCROW nRow ) const
 {
     if (ValidColRow( nCol, nRow ))
         return aCol[nCol].GetValue( nRow );
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 598a833..a7604dd 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1081,7 +1081,7 @@ bool isQueryByValue(
 }
 
 std::pair<bool,bool> compareByValue(
-    ScDocument& rDoc, ScTable& rTab, const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
+    const ScDocument& rDoc, const ScTable& rTab, const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
     const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool* pbTestEqualCondition)
 {
     bool bOk = false;
@@ -1237,7 +1237,7 @@ bool isTestRegExp(const ScQueryParam& rParam, const ScQueryEntry& rEntry, bool*
 }
 
 std::pair<bool,bool> compareByString(
-    ScDocument& rDoc, ScTable& rTab, ScBaseCell* pCell, SCROW nRow,
+    const ScDocument& rDoc, const ScTable& rTab, ScBaseCell* pCell, SCROW nRow,
     const ScQueryParam& rParam, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool bMatchWholeCell,
     ::utl::TransliterationWrapper* pTransliteration, CollatorWrapper* pCollator,
     bool* pbTestEqualCondition)
@@ -1254,7 +1254,7 @@ std::pair<bool,bool> compareByString(
         if (pCell->GetCellType() != CELLTYPE_NOTE)
         {
             sal_uLong nFormat = rTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
-            ScCellFormat::GetInputString( pCell, nFormat, aCellStr, *(rDoc.GetFormatTable()) );
+            ScCellFormat::GetInputString(pCell, nFormat, aCellStr, *rDoc.GetFormatTable());
         }
     }
     else
commit 05dc62da44f0853bebf68e6f6c695900090a15ba
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Mon Nov 14 14:18:59 2011 -0500

    Extracted compare-by-value and compare-by-string into functions.

diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 4539055..598a833 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1080,6 +1080,92 @@ bool isQueryByValue(
     return rTable.HasValueData(nCol, nRow);
 }
 
+std::pair<bool,bool> compareByValue(
+    ScDocument& rDoc, ScTable& rTab, const ScBaseCell* pCell, SCCOL nCol, SCROW nRow,
+    const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool* pbTestEqualCondition)
+{
+    bool bOk = false;
+    bool bTestEqual = false;
+    double nCellVal;
+    if ( pCell )
+    {
+        switch ( pCell->GetCellType() )
+        {
+            case CELLTYPE_VALUE :
+                nCellVal = ((ScValueCell*)pCell)->GetValue();
+            break;
+            case CELLTYPE_FORMULA :
+                nCellVal = ((ScFormulaCell*)pCell)->GetValue();
+            break;
+            default:
+                nCellVal = 0.0;
+        }
+
+    }
+    else
+        nCellVal = rTab.GetValue(nCol, nRow);
+
+    /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
+     * date+time format was queried rEntry.bQueryByDate is not set. In
+     * case other queries wanted to use this mechanism they should do
+     * the same, in other words only if rEntry.nVal is an integer value
+     * rEntry.bQueryByDate should be true and the time fraction be
+     * stripped here. */
+    if (rItem.meType == ScQueryEntry::ByDate)
+    {
+        sal_uInt32 nNumFmt = rTab.GetNumberFormat(nCol, nRow);
+        const SvNumberformat* pEntry = rDoc.GetFormatTable()->GetEntry(nNumFmt);
+        if (pEntry)
+        {
+            short nNumFmtType = pEntry->GetType();
+            /* NOTE: Omitting the check for absence of
+             * NUMBERFORMAT_TIME would include also date+time formatted
+             * values of the same day. That may be desired in some
+             * cases, querying all time values of a day, but confusing
+             * in other cases. A user can always setup a standard
+             * filter query for x >= date AND x < date+1 */
+            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 :
+            bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+            break;
+        case SC_LESS :
+            bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+            break;
+        case SC_GREATER :
+            bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+            break;
+        case SC_LESS_EQUAL :
+            bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+            if ( bOk && pbTestEqualCondition )
+                bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+            break;
+        case SC_GREATER_EQUAL :
+            bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual( nCellVal, rItem.mfVal);
+            if ( bOk && pbTestEqualCondition )
+                bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+            break;
+        case SC_NOT_EQUAL :
+            bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
+            break;
+        default:
+        {
+            // added to avoid warnings
+        }
+    }
+
+    return std::pair<bool,bool>(bOk, bTestEqual);
+}
+
 bool isPartialTextMatchOp(const ScQueryEntry& rEntry)
 {
     switch (rEntry.eOp)
@@ -1150,6 +1236,180 @@ bool isTestRegExp(const ScQueryParam& rParam, const ScQueryEntry& rEntry, bool*
     return (rEntry.eOp == SC_LESS_EQUAL || rEntry.eOp == SC_GREATER_EQUAL);
 }
 
+std::pair<bool,bool> compareByString(
+    ScDocument& rDoc, ScTable& rTab, ScBaseCell* pCell, SCROW nRow,
+    const ScQueryParam& rParam, const ScQueryEntry& rEntry, const ScQueryEntry::Item& rItem, bool bMatchWholeCell,
+    ::utl::TransliterationWrapper* pTransliteration, CollatorWrapper* pCollator,
+    bool* pbTestEqualCondition)
+{
+    bool bOk = false;
+    bool bTestEqual = false;
+    rtl::OUString  aCellStr;
+    if (isPartialTextMatchOp(rEntry))
+        // may have to do partial textural comparison.
+        bMatchWholeCell = false;
+
+    if ( pCell )
+    {
+        if (pCell->GetCellType() != CELLTYPE_NOTE)
+        {
+            sal_uLong nFormat = rTab.GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
+            ScCellFormat::GetInputString( pCell, nFormat, aCellStr, *(rDoc.GetFormatTable()) );
+        }
+    }
+    else
+        rTab.GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
+
+    bool bRealRegExp = isRealRegExp(rParam, rEntry);
+    bool bTestRegExp = isTestRegExp(rParam, rEntry, pbTestEqualCondition);
+
+    if ( bRealRegExp || bTestRegExp )
+    {
+        xub_StrLen nStart = 0;
+        xub_StrLen nEnd   = aCellStr.getLength();
+
+        // from 614 on, nEnd is behind the found text
+        bool bMatch = false;
+        if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
+        {
+            nEnd = 0;
+            nStart = aCellStr.getLength();
+            bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+                ->SearchBkwrd( aCellStr, &nStart, &nEnd );
+        }
+        else
+        {
+            bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
+                ->SearchFrwrd( aCellStr, &nStart, &nEnd );
+        }
+        if ( bMatch && bMatchWholeCell
+                && (nStart != 0 || nEnd != aCellStr.getLength()) )
+            bMatch = false;    // RegExp must match entire cell string
+        if ( bRealRegExp )
+            switch (rEntry.eOp)
+        {
+            case SC_EQUAL:
+            case SC_CONTAINS:
+                bOk = bMatch;
+                break;
+            case SC_NOT_EQUAL:
+            case SC_DOES_NOT_CONTAIN:
+                bOk = !bMatch;
+                break;
+            case SC_BEGINS_WITH:
+                bOk = ( bMatch && (nStart == 0) );
+                break;
+            case SC_DOES_NOT_BEGIN_WITH:
+                bOk = !( bMatch && (nStart == 0) );
+                break;
+            case SC_ENDS_WITH:
+                bOk = ( bMatch && (nEnd == aCellStr.getLength()) );
+                break;
+            case SC_DOES_NOT_END_WITH:
+                bOk = !( bMatch && (nEnd == aCellStr.getLength()) );
+                break;
+            default:
+                {
+                    // added to avoid warnings
+                }
+        }
+        else
+            bTestEqual = bMatch;
+    }
+    if ( !bRealRegExp )
+    {
+        // Simple string matching i.e. no regexp match.
+        if (isTextMatchOp(rEntry))
+        {
+            if (!rItem.meType != ScQueryEntry::ByString && rItem.maString.isEmpty())
+            {
+                // #i18374# When used from functions (match, countif, sumif, vlookup, hlookup, lookup),
+                // the query value is assigned directly, and the string is empty. In that case,
+                // don't find any string (isEqual would find empty string results in formula cells).
+                bOk = false;
+                if ( rEntry.eOp == SC_NOT_EQUAL )
+                    bOk = !bOk;
+            }
+            else if ( bMatchWholeCell )
+            {
+                bOk = pTransliteration->isEqual(aCellStr, rEntry.GetQueryItem().maString);
+                if ( rEntry.eOp == SC_NOT_EQUAL )
+                    bOk = !bOk;
+            }
+            else
+            {
+                const rtl::OUString& rQueryStr = rItem.maString;
+                String aCell( pTransliteration->transliterate(
+                    aCellStr, ScGlobal::eLnge, 0, aCellStr.getLength(),
+                    NULL ) );
+                String aQuer( pTransliteration->transliterate(
+                    rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(),
+                    NULL ) );
+                xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
+                    || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
+                xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
+                switch (rEntry.eOp)
+                {
+                case SC_EQUAL:
+                case SC_CONTAINS:
+                    bOk = ( nStrPos != STRING_NOTFOUND );
+                    break;
+                case SC_NOT_EQUAL:
+                case SC_DOES_NOT_CONTAIN:
+                    bOk = ( nStrPos == STRING_NOTFOUND );
+                    break;
+                case SC_BEGINS_WITH:
+                    bOk = ( nStrPos == 0 );
+                    break;
+                case SC_DOES_NOT_BEGIN_WITH:
+                    bOk = ( nStrPos != 0 );
+                    break;
+                case SC_ENDS_WITH:
+                    bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
+                    break;
+                case SC_DOES_NOT_END_WITH:
+                    bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
+                    break;
+                default:
+                    {
+                        // added to avoid warnings
+                    }
+                }
+            }
+        }
+        else
+        {   // use collator here because data was probably sorted
+            sal_Int32 nCompare = pCollator->compareString(
+                aCellStr, rEntry.GetQueryItem().maString);
+            switch (rEntry.eOp)
+            {
+                case SC_LESS :
+                    bOk = (nCompare < 0);
+                    break;
+                case SC_GREATER :
+                    bOk = (nCompare > 0);
+                    break;
+                case SC_LESS_EQUAL :
+                    bOk = (nCompare <= 0);
+                    if ( bOk && pbTestEqualCondition && !bTestEqual )
+                        bTestEqual = (nCompare == 0);
+                    break;
+                case SC_GREATER_EQUAL :
+                    bOk = (nCompare >= 0);
+                    if ( bOk && pbTestEqualCondition && !bTestEqual )
+                        bTestEqual = (nCompare == 0);
+                    break;
+                default:
+                {
+                    // added to avoid warnings
+                }
+            }
+        }
+    }
+
+    return std::pair<bool,bool>(bOk, bTestEqual);
+}
+
 }
 
 bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
@@ -1200,247 +1460,18 @@ bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
         }
         else if (isQueryByValue(*this, rItem, nCol, nRow, pCell))
         {
-            double nCellVal;
-            if ( pCell )
-            {
-                switch ( pCell->GetCellType() )
-                {
-                    case CELLTYPE_VALUE :
-                        nCellVal = ((ScValueCell*)pCell)->GetValue();
-                    break;
-                    case CELLTYPE_FORMULA :
-                        nCellVal = ((ScFormulaCell*)pCell)->GetValue();
-                    break;
-                    default:
-                        nCellVal = 0.0;
-                }
-
-            }
-            else
-                nCellVal = GetValue(nCol, nRow);
-
-            /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
-             * date+time format was queried rEntry.bQueryByDate is not set. In
-             * case other queries wanted to use this mechanism they should do
-             * the same, in other words only if rEntry.nVal is an integer value
-             * rEntry.bQueryByDate should be true and the time fraction be
-             * stripped here. */
-            if (rItem.meType == ScQueryEntry::ByDate)
-            {
-                sal_uInt32 nNumFmt = GetNumberFormat(nCol, nRow);
-                const SvNumberformat* pEntry = pDocument->GetFormatTable()->GetEntry(nNumFmt);
-                if (pEntry)
-                {
-                    short nNumFmtType = pEntry->GetType();
-                    /* NOTE: Omitting the check for absence of
-                     * NUMBERFORMAT_TIME would include also date+time formatted
-                     * values of the same day. That may be desired in some
-                     * cases, querying all time values of a day, but confusing
-                     * in other cases. A user can always setup a standard
-                     * filter query for x >= date AND x < date+1 */
-                    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 :
-                    bOk = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_LESS :
-                    bOk = (nCellVal < rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_GREATER :
-                    bOk = (nCellVal > rItem.mfVal) && !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_LESS_EQUAL :
-                    bOk = (nCellVal < rItem.mfVal) || ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    if ( bOk && pbTestEqualCondition )
-                        bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_GREATER_EQUAL :
-                    bOk = (nCellVal > rItem.mfVal) || ::rtl::math::approxEqual( nCellVal, rItem.mfVal);
-                    if ( bOk && pbTestEqualCondition )
-                        bTestEqual = ::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                case SC_NOT_EQUAL :
-                    bOk = !::rtl::math::approxEqual(nCellVal, rItem.mfVal);
-                    break;
-                default:
-                {
-                    // added to avoid warnings
-                }
-            }
+            std::pair<bool,bool> res = compareByValue(
+                *pDocument, *this, pCell, nCol, nRow, rEntry, rItem, pbTestEqualCondition);
+            bOk = res.first;
+            bTestEqual = res.second;
         }
         else if (isQueryByString(*this, rEntry, rItem, nCol, nRow, pCell))
         {
-            rtl::OUString  aCellStr;
-            if (isPartialTextMatchOp(rEntry))
-                // may have to do partial textural comparison.
-                bMatchWholeCell = false;
-
-            if ( pCell )
-            {
-                if (pCell->GetCellType() != CELLTYPE_NOTE)
-                {
-                    sal_uLong nFormat = GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
-                    ScCellFormat::GetInputString( pCell, nFormat, aCellStr, *(pDocument->GetFormatTable()) );
-                }
-            }
-            else
-                GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
-
-            bool bRealRegExp = isRealRegExp(rParam, rEntry);
-            bool bTestRegExp = isTestRegExp(rParam, rEntry, pbTestEqualCondition);
-
-            if ( bRealRegExp || bTestRegExp )
-            {
-                xub_StrLen nStart = 0;
-                xub_StrLen nEnd   = aCellStr.getLength();
-
-                // from 614 on, nEnd is behind the found text
-                bool bMatch = false;
-                if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
-                {
-                    nEnd = 0;
-                    nStart = aCellStr.getLength();
-                    bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
-                        ->SearchBkwrd( aCellStr, &nStart, &nEnd );
-                }
-                else
-                {
-                    bMatch = (bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
-                        ->SearchFrwrd( aCellStr, &nStart, &nEnd );
-                }
-                if ( bMatch && bMatchWholeCell
-                        && (nStart != 0 || nEnd != aCellStr.getLength()) )
-                    bMatch = false;    // RegExp must match entire cell string
-                if ( bRealRegExp )
-                    switch (rEntry.eOp)
-                {
-                    case SC_EQUAL:
-                    case SC_CONTAINS:
-                        bOk = bMatch;
-                        break;
-                    case SC_NOT_EQUAL:
-                    case SC_DOES_NOT_CONTAIN:
-                        bOk = !bMatch;
-                        break;
-                    case SC_BEGINS_WITH:
-                        bOk = ( bMatch && (nStart == 0) );
-                        break;
-                    case SC_DOES_NOT_BEGIN_WITH:
-                        bOk = !( bMatch && (nStart == 0) );
-                        break;
-                    case SC_ENDS_WITH:
-                        bOk = ( bMatch && (nEnd == aCellStr.getLength()) );
-                        break;
-                    case SC_DOES_NOT_END_WITH:
-                        bOk = !( bMatch && (nEnd == aCellStr.getLength()) );
-                        break;
-                    default:
-                        {
-                            // added to avoid warnings
-                        }
-                }
-                else
-                    bTestEqual = bMatch;
-            }
-            if ( !bRealRegExp )
-            {
-                // Simple string matching i.e. no regexp match.
-                if (isTextMatchOp(rEntry))
-                {
-                    if (!rItem.meType != ScQueryEntry::ByString && rItem.maString.isEmpty())
-                    {
-                        // #i18374# When used from functions (match, countif, sumif, vlookup, hlookup, lookup),
-                        // the query value is assigned directly, and the string is empty. In that case,
-                        // don't find any string (isEqual would find empty string results in formula cells).
-                        bOk = false;
-                        if ( rEntry.eOp == SC_NOT_EQUAL )
-                            bOk = !bOk;
-                    }
-                    else if ( bMatchWholeCell )
-                    {
-                        bOk = pTransliteration->isEqual(aCellStr, rEntry.GetQueryItem().maString);
-                        if ( rEntry.eOp == SC_NOT_EQUAL )
-                            bOk = !bOk;
-                    }
-                    else
-                    {
-                        const rtl::OUString& rQueryStr = rItem.maString;
-                        String aCell( pTransliteration->transliterate(
-                            aCellStr, ScGlobal::eLnge, 0, aCellStr.getLength(),
-                            NULL ) );
-                        String aQuer( pTransliteration->transliterate(
-                            rQueryStr, ScGlobal::eLnge, 0, rQueryStr.getLength(),
-                            NULL ) );
-                        xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
-                            || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
-                        xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
-                        switch (rEntry.eOp)
-                        {
-                        case SC_EQUAL:
-                        case SC_CONTAINS:
-                            bOk = ( nStrPos != STRING_NOTFOUND );
-                            break;
-                        case SC_NOT_EQUAL:
-                        case SC_DOES_NOT_CONTAIN:
-                            bOk = ( nStrPos == STRING_NOTFOUND );
-                            break;
-                        case SC_BEGINS_WITH:
-                            bOk = ( nStrPos == 0 );
-                            break;
-                        case SC_DOES_NOT_BEGIN_WITH:
-                            bOk = ( nStrPos != 0 );
-                            break;
-                        case SC_ENDS_WITH:
-                            bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
-                            break;
-                        case SC_DOES_NOT_END_WITH:
-                            bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
-                            break;
-                        default:
-                            {
-                                // added to avoid warnings
-                            }
-                        }
-                    }
-                }
-                else
-                {   // use collator here because data was probably sorted
-                    sal_Int32 nCompare = pCollator->compareString(
-                        aCellStr, rEntry.GetQueryItem().maString);
-                    switch (rEntry.eOp)
-                    {
-                        case SC_LESS :
-                            bOk = (nCompare < 0);
-                            break;
-                        case SC_GREATER :
-                            bOk = (nCompare > 0);
-                            break;
-                        case SC_LESS_EQUAL :
-                            bOk = (nCompare <= 0);
-                            if ( bOk && pbTestEqualCondition && !bTestEqual )
-                                bTestEqual = (nCompare == 0);
-                            break;
-                        case SC_GREATER_EQUAL :
-                            bOk = (nCompare >= 0);
-                            if ( bOk && pbTestEqualCondition && !bTestEqual )
-                                bTestEqual = (nCompare == 0);
-                            break;
-                        default:
-                        {
-                            // added to avoid warnings
-                        }
-                    }
-                }
-            }
+            std::pair<bool,bool> res = compareByString(
+                *pDocument, *this, pCell, nRow, rParam, rEntry, rItem, bMatchWholeCell,
+                pTransliteration, pCollator, pbTestEqualCondition);
+            bOk = res.first;
+            bTestEqual = res.second;
         }
 
         if (nPos == -1)


More information about the Libreoffice-commits mailing list