1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "queryparam.hxx"
21 #include "queryentry.hxx"
22 #include "scmatrix.hxx"
24 #include <svl/sharedstringpool.hxx>
25 #include <svl/zforlist.hxx>
26 #include <osl/diagnose.h>
30 const size_t MAXQUERY
= 8;
32 class FindByField
: public std::unary_function
<ScQueryEntry
, bool>
36 FindByField(SCCOLROW nField
) : mnField(nField
) {}
37 bool operator() (const ScQueryEntry
& rEntry
) const
39 return rEntry
.bDoQuery
&& rEntry
.nField
== mnField
;
43 struct FindUnused
: public std::unary_function
<ScQueryEntry
, bool>
45 bool operator() (const ScQueryEntry
& rEntry
) const
47 return !rEntry
.bDoQuery
;
53 ScQueryParamBase::const_iterator
ScQueryParamBase::begin() const
55 return maEntries
.begin();
58 ScQueryParamBase::const_iterator
ScQueryParamBase::end() const
60 return maEntries
.end();
63 ScQueryParamBase::ScQueryParamBase() :
72 for (size_t i
= 0; i
< MAXQUERY
; ++i
)
73 maEntries
.push_back(new ScQueryEntry
);
76 ScQueryParamBase::ScQueryParamBase(const ScQueryParamBase
& r
) :
77 bHasHeader(r
.bHasHeader
), bByRow(r
.bByRow
), bInplace(r
.bInplace
), bCaseSens(r
.bCaseSens
),
78 bRegExp(r
.bRegExp
), bDuplicate(r
.bDuplicate
), mbRangeLookup(r
.mbRangeLookup
),
79 maEntries(r
.maEntries
)
83 ScQueryParamBase::~ScQueryParamBase()
87 bool ScQueryParamBase::IsValidFieldIndex() const
92 SCSIZE
ScQueryParamBase::GetEntryCount() const
94 return maEntries
.size();
97 const ScQueryEntry
& ScQueryParamBase::GetEntry(SCSIZE n
) const
102 ScQueryEntry
& ScQueryParamBase::GetEntry(SCSIZE n
)
107 ScQueryEntry
& ScQueryParamBase::AppendEntry()
109 // Find the first unused entry.
110 EntriesType::iterator itr
= std::find_if(
111 maEntries
.begin(), maEntries
.end(), FindUnused());
113 if (itr
!= maEntries
.end())
117 // Add a new entry to the end.
118 maEntries
.push_back(new ScQueryEntry
);
119 return maEntries
.back();
122 ScQueryEntry
* ScQueryParamBase::FindEntryByField(SCCOLROW nField
, bool bNew
)
124 EntriesType::iterator itr
= std::find_if(
125 maEntries
.begin(), maEntries
.end(), FindByField(nField
));
127 if (itr
!= maEntries
.end())
129 // existing entry found!
134 // no existing entry found, and we are not creating a new one.
137 return &AppendEntry();
140 void ScQueryParamBase::RemoveEntryByField(SCCOLROW nField
)
142 EntriesType::iterator itr
= std::find_if(
143 maEntries
.begin(), maEntries
.end(), FindByField(nField
));
145 if (itr
!= maEntries
.end())
147 maEntries
.erase(itr
);
148 if (maEntries
.size() < MAXQUERY
)
149 // Make sure that we have at least MAXQUERY number of entries at
151 maEntries
.push_back(new ScQueryEntry
);
155 void ScQueryParamBase::Resize(size_t nNew
)
158 nNew
= MAXQUERY
; // never less than MAXQUERY
160 if (nNew
< maEntries
.size())
162 size_t n
= maEntries
.size() - nNew
;
163 for (size_t i
= 0; i
< n
; ++i
)
164 maEntries
.pop_back();
166 else if (nNew
> maEntries
.size())
168 size_t n
= nNew
- maEntries
.size();
169 for (size_t i
= 0; i
< n
; ++i
)
170 maEntries
.push_back(new ScQueryEntry
);
174 void ScQueryParamBase::FillInExcelSyntax(
175 svl::SharedStringPool
& rPool
, const OUString
& rStr
, SCSIZE nIndex
, SvNumberFormatter
* pFormatter
)
177 const OUString aCellStr
= rStr
;
178 if (nIndex
>= maEntries
.size())
181 ScQueryEntry
& rEntry
= GetEntry(nIndex
);
182 ScQueryEntry::Item
& rItem
= rEntry
.GetQueryItem();
184 if (aCellStr
.isEmpty())
185 rItem
.maString
= svl::SharedString::getEmptyString();
188 rEntry
.bDoQuery
= true;
189 // Operatoren herausfiltern
190 if (aCellStr
[0] == '<')
192 if (aCellStr
[1] == '>')
194 rItem
.maString
= rPool
.intern(aCellStr
.copy(2));
195 rEntry
.eOp
= SC_NOT_EQUAL
;
197 else if (aCellStr
[1] == '=')
199 rItem
.maString
= rPool
.intern(aCellStr
.copy(2));
200 rEntry
.eOp
= SC_LESS_EQUAL
;
204 rItem
.maString
= rPool
.intern(aCellStr
.copy(1));
205 rEntry
.eOp
= SC_LESS
;
208 else if (aCellStr
[0]== '>')
210 if (aCellStr
[1] == '=')
212 rItem
.maString
= rPool
.intern(aCellStr
.copy(2));
213 rEntry
.eOp
= SC_GREATER_EQUAL
;
217 rItem
.maString
= rPool
.intern(aCellStr
.copy(1));
218 rEntry
.eOp
= SC_GREATER
;
223 if (aCellStr
[0] == '=')
224 rItem
.maString
= rPool
.intern(aCellStr
.copy(1));
226 rItem
.maString
= rPool
.intern(aCellStr
);
227 rEntry
.eOp
= SC_EQUAL
;
233 sal_uInt32 nFormat
= 0;
234 bool bNumber
= pFormatter
->IsNumberFormat( rItem
.maString
.getString(), nFormat
, rItem
.mfVal
);
235 rItem
.meType
= bNumber
? ScQueryEntry::ByValue
: ScQueryEntry::ByString
;
237 /* TODO: pFormatter currently is also used as a flag whether matching
238 * empty cells with an empty string is triggered from the interpreter.
239 * This could be handled independently if all queries should support
240 * it, needs to be evaluated if that actually is desired. */
241 if (rItem
.meType
== ScQueryEntry::ByString
)
242 rItem
.mbMatchEmpty
= (rEntry
.eOp
== SC_EQUAL
&& rItem
.maString
.isEmpty());
246 ScQueryParamTable::ScQueryParamTable() :
247 nCol1(0),nRow1(0),nCol2(0),nRow2(0),nTab(0)
251 ScQueryParamTable::ScQueryParamTable(const ScQueryParamTable
& r
) :
252 nCol1(r
.nCol1
),nRow1(r
.nRow1
),nCol2(r
.nCol2
),nRow2(r
.nRow2
),nTab(r
.nTab
)
256 ScQueryParamTable::~ScQueryParamTable()
260 ScQueryParam::ScQueryParam() :
271 ScQueryParam::ScQueryParam( const ScQueryParam
& r
) :
273 ScQueryParamTable(r
),
274 bDestPers(r
.bDestPers
), nDestTab(r
.nDestTab
), nDestCol(r
.nDestCol
), nDestRow(r
.nDestRow
)
278 ScQueryParam::ScQueryParam( const ScDBQueryParamInternal
& r
) :
280 ScQueryParamTable(r
),
288 ScQueryParam::~ScQueryParam()
292 void ScQueryParam::Clear()
297 bHasHeader
= bCaseSens
= bRegExp
= false;
298 bInplace
= bByRow
= bDuplicate
= true;
300 boost::ptr_vector
<ScQueryEntry
>::iterator itr
= maEntries
.begin(), itrEnd
= maEntries
.end();
301 for (; itr
!= itrEnd
; ++itr
)
307 void ScQueryParam::ClearDestParams()
315 ScQueryParam
& ScQueryParam::operator=( const ScQueryParam
& r
)
322 nDestTab
= r
.nDestTab
;
323 nDestCol
= r
.nDestCol
;
324 nDestRow
= r
.nDestRow
;
325 bHasHeader
= r
.bHasHeader
;
326 bInplace
= r
.bInplace
;
327 bCaseSens
= r
.bCaseSens
;
329 bDuplicate
= r
.bDuplicate
;
331 bDestPers
= r
.bDestPers
;
333 maEntries
= r
.maEntries
.clone();
338 bool ScQueryParam::operator==( const ScQueryParam
& rOther
) const
342 // Anzahl der Queries gleich?
344 SCSIZE nOtherUsed
= 0;
345 SCSIZE nEntryCount
= GetEntryCount();
346 SCSIZE nOtherEntryCount
= rOther
.GetEntryCount();
348 while ( nUsed
<nEntryCount
&& maEntries
[nUsed
].bDoQuery
) ++nUsed
;
349 while ( nOtherUsed
<nOtherEntryCount
&& rOther
.maEntries
[nOtherUsed
].bDoQuery
)
352 if ( (nUsed
== nOtherUsed
)
353 && (nCol1
== rOther
.nCol1
)
354 && (nRow1
== rOther
.nRow1
)
355 && (nCol2
== rOther
.nCol2
)
356 && (nRow2
== rOther
.nRow2
)
357 && (nTab
== rOther
.nTab
)
358 && (bHasHeader
== rOther
.bHasHeader
)
359 && (bByRow
== rOther
.bByRow
)
360 && (bInplace
== rOther
.bInplace
)
361 && (bCaseSens
== rOther
.bCaseSens
)
362 && (bRegExp
== rOther
.bRegExp
)
363 && (bDuplicate
== rOther
.bDuplicate
)
364 && (bDestPers
== rOther
.bDestPers
)
365 && (nDestTab
== rOther
.nDestTab
)
366 && (nDestCol
== rOther
.nDestCol
)
367 && (nDestRow
== rOther
.nDestRow
) )
370 for ( SCSIZE i
=0; i
<nUsed
&& bEqual
; i
++ )
371 bEqual
= maEntries
[i
] == rOther
.maEntries
[i
];
376 void ScQueryParam::MoveToDest()
380 SCsCOL nDifX
= ((SCsCOL
) nDestCol
) - ((SCsCOL
) nCol1
);
381 SCsROW nDifY
= ((SCsROW
) nDestRow
) - ((SCsROW
) nRow1
);
382 SCsTAB nDifZ
= ((SCsTAB
) nDestTab
) - ((SCsTAB
) nTab
);
384 nCol1
= sal::static_int_cast
<SCCOL
>( nCol1
+ nDifX
);
385 nRow1
= sal::static_int_cast
<SCROW
>( nRow1
+ nDifY
);
386 nCol2
= sal::static_int_cast
<SCCOL
>( nCol2
+ nDifX
);
387 nRow2
= sal::static_int_cast
<SCROW
>( nRow2
+ nDifY
);
388 nTab
= sal::static_int_cast
<SCTAB
>( nTab
+ nDifZ
);
389 size_t n
= maEntries
.size();
390 for (size_t i
=0; i
<n
; i
++)
391 maEntries
[i
].nField
+= nDifX
;
397 OSL_FAIL("MoveToDest, bInplace == TRUE");
401 ScDBQueryParamBase::ScDBQueryParamBase(DataType eType
) :
409 ScDBQueryParamBase::~ScDBQueryParamBase()
413 ScDBQueryParamInternal::ScDBQueryParamInternal() :
414 ScDBQueryParamBase(ScDBQueryParamBase::INTERNAL
),
419 ScDBQueryParamInternal::~ScDBQueryParamInternal()
423 bool ScDBQueryParamInternal::IsValidFieldIndex() const
425 return nCol1
<= mnField
&& mnField
<= nCol2
;
428 ScDBQueryParamMatrix::ScDBQueryParamMatrix() :
429 ScDBQueryParamBase(ScDBQueryParamBase::MATRIX
)
433 bool ScDBQueryParamMatrix::IsValidFieldIndex() const
436 mpMatrix
->GetDimensions(nC
, nR
);
437 return 0 <= mnField
&& mnField
<= static_cast<SCCOL
>(nC
);
440 ScDBQueryParamMatrix::~ScDBQueryParamMatrix()
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */