Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "queryparam.hxx"
21 : #include "queryentry.hxx"
22 : #include "scmatrix.hxx"
23 :
24 : #include <svl/sharedstringpool.hxx>
25 : #include <svl/zforlist.hxx>
26 : #include <osl/diagnose.h>
27 :
28 : namespace {
29 :
30 : const size_t MAXQUERY = 8;
31 :
32 : class FindByField : public std::unary_function<ScQueryEntry, bool>
33 : {
34 : SCCOLROW mnField;
35 : public:
36 3 : FindByField(SCCOLROW nField) : mnField(nField) {}
37 17 : bool operator() (const ScQueryEntry& rEntry) const
38 : {
39 17 : return rEntry.bDoQuery && rEntry.nField == mnField;
40 : }
41 : };
42 :
43 : struct FindUnused : public std::unary_function<ScQueryEntry, bool>
44 : {
45 10 : bool operator() (const ScQueryEntry& rEntry) const
46 : {
47 10 : return !rEntry.bDoQuery;
48 : }
49 : };
50 :
51 : }
52 :
53 1049 : ScQueryParamBase::const_iterator ScQueryParamBase::begin() const
54 : {
55 1049 : return maEntries.begin();
56 : }
57 :
58 1049 : ScQueryParamBase::const_iterator ScQueryParamBase::end() const
59 : {
60 1049 : return maEntries.end();
61 : }
62 :
63 680 : ScQueryParamBase::ScQueryParamBase() :
64 : bHasHeader(true),
65 : bByRow(true),
66 : bInplace(true),
67 : bCaseSens(false),
68 : bRegExp(false),
69 : bDuplicate(false),
70 680 : mbRangeLookup(false)
71 : {
72 6120 : for (size_t i = 0; i < MAXQUERY; ++i)
73 5440 : maEntries.push_back(new ScQueryEntry);
74 680 : }
75 :
76 1276 : 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 1276 : maEntries(r.maEntries)
80 : {
81 1276 : }
82 :
83 1911 : ScQueryParamBase::~ScQueryParamBase()
84 : {
85 1911 : }
86 :
87 0 : bool ScQueryParamBase::IsValidFieldIndex() const
88 : {
89 0 : return true;
90 : }
91 :
92 3222 : SCSIZE ScQueryParamBase::GetEntryCount() const
93 : {
94 3222 : return maEntries.size();
95 : }
96 :
97 2838 : const ScQueryEntry& ScQueryParamBase::GetEntry(SCSIZE n) const
98 : {
99 2838 : return maEntries[n];
100 : }
101 :
102 6527 : ScQueryEntry& ScQueryParamBase::GetEntry(SCSIZE n)
103 : {
104 6527 : return maEntries[n];
105 : }
106 :
107 9 : ScQueryEntry& ScQueryParamBase::AppendEntry()
108 : {
109 : // Find the first unused entry.
110 : EntriesType::iterator itr = std::find_if(
111 9 : maEntries.begin(), maEntries.end(), FindUnused());
112 :
113 9 : if (itr != maEntries.end())
114 : // Found!
115 9 : return *itr;
116 :
117 : // Add a new entry to the end.
118 0 : maEntries.push_back(new ScQueryEntry);
119 0 : return maEntries.back();
120 : }
121 :
122 0 : ScQueryEntry* ScQueryParamBase::FindEntryByField(SCCOLROW nField, bool bNew)
123 : {
124 : EntriesType::iterator itr = std::find_if(
125 0 : maEntries.begin(), maEntries.end(), FindByField(nField));
126 :
127 0 : if (itr != maEntries.end())
128 : {
129 : // existing entry found!
130 0 : return &(*itr);
131 : }
132 :
133 0 : if (!bNew)
134 : // no existing entry found, and we are not creating a new one.
135 0 : return NULL;
136 :
137 0 : return &AppendEntry();
138 : }
139 :
140 3 : void ScQueryParamBase::RemoveEntryByField(SCCOLROW nField)
141 : {
142 : EntriesType::iterator itr = std::find_if(
143 3 : maEntries.begin(), maEntries.end(), FindByField(nField));
144 :
145 3 : if (itr != maEntries.end())
146 : {
147 1 : maEntries.erase(itr);
148 1 : if (maEntries.size() < MAXQUERY)
149 : // Make sure that we have at least MAXQUERY number of entries at
150 : // all times.
151 1 : maEntries.push_back(new ScQueryEntry);
152 : }
153 3 : }
154 :
155 29 : void ScQueryParamBase::Resize(size_t nNew)
156 : {
157 29 : if (nNew < MAXQUERY)
158 29 : nNew = MAXQUERY; // never less than MAXQUERY
159 :
160 29 : if (nNew < maEntries.size())
161 : {
162 0 : size_t n = maEntries.size() - nNew;
163 0 : for (size_t i = 0; i < n; ++i)
164 0 : maEntries.pop_back();
165 : }
166 29 : else if (nNew > maEntries.size())
167 : {
168 0 : size_t n = nNew - maEntries.size();
169 0 : for (size_t i = 0; i < n; ++i)
170 0 : maEntries.push_back(new ScQueryEntry);
171 : }
172 29 : }
173 :
174 59 : void ScQueryParamBase::FillInExcelSyntax(
175 : svl::SharedStringPool& rPool, const OUString& rStr, SCSIZE nIndex, SvNumberFormatter* pFormatter )
176 : {
177 59 : const OUString aCellStr = rStr;
178 59 : if (nIndex >= maEntries.size())
179 0 : Resize(nIndex+1);
180 :
181 59 : ScQueryEntry& rEntry = GetEntry(nIndex);
182 59 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
183 :
184 59 : if (aCellStr.isEmpty())
185 1 : rItem.maString = svl::SharedString::getEmptyString();
186 : else
187 : {
188 58 : rEntry.bDoQuery = true;
189 : // Operatoren herausfiltern
190 58 : if (aCellStr[0] == '<')
191 : {
192 13 : if (aCellStr[1] == '>')
193 : {
194 0 : rItem.maString = rPool.intern(aCellStr.copy(2));
195 0 : rEntry.eOp = SC_NOT_EQUAL;
196 : }
197 13 : else if (aCellStr[1] == '=')
198 : {
199 6 : rItem.maString = rPool.intern(aCellStr.copy(2));
200 6 : rEntry.eOp = SC_LESS_EQUAL;
201 : }
202 : else
203 : {
204 7 : rItem.maString = rPool.intern(aCellStr.copy(1));
205 7 : rEntry.eOp = SC_LESS;
206 : }
207 : }
208 45 : else if (aCellStr[0]== '>')
209 : {
210 21 : if (aCellStr[1] == '=')
211 : {
212 15 : rItem.maString = rPool.intern(aCellStr.copy(2));
213 15 : rEntry.eOp = SC_GREATER_EQUAL;
214 : }
215 : else
216 : {
217 6 : rItem.maString = rPool.intern(aCellStr.copy(1));
218 6 : rEntry.eOp = SC_GREATER;
219 : }
220 : }
221 : else
222 : {
223 24 : if (aCellStr[0] == '=')
224 0 : rItem.maString = rPool.intern(aCellStr.copy(1));
225 : else
226 24 : rItem.maString = rPool.intern(aCellStr);
227 24 : rEntry.eOp = SC_EQUAL;
228 : }
229 : }
230 :
231 59 : if (pFormatter)
232 : {
233 47 : sal_uInt32 nFormat = 0;
234 47 : bool bNumber = pFormatter->IsNumberFormat( rItem.maString.getString(), nFormat, rItem.mfVal);
235 47 : rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
236 :
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 47 : if (rItem.meType == ScQueryEntry::ByString)
242 17 : rItem.mbMatchEmpty = (rEntry.eOp == SC_EQUAL && rItem.maString.isEmpty());
243 59 : }
244 59 : }
245 :
246 680 : ScQueryParamTable::ScQueryParamTable() :
247 680 : nCol1(0),nRow1(0),nCol2(0),nRow2(0),nTab(0)
248 : {
249 680 : }
250 :
251 1276 : ScQueryParamTable::ScQueryParamTable(const ScQueryParamTable& r) :
252 1276 : nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab)
253 : {
254 1276 : }
255 :
256 1911 : ScQueryParamTable::~ScQueryParamTable()
257 : {
258 1911 : }
259 :
260 672 : ScQueryParam::ScQueryParam() :
261 : ScQueryParamBase(),
262 : ScQueryParamTable(),
263 : bDestPers(true),
264 : nDestTab(0),
265 : nDestCol(0),
266 672 : nDestRow(0)
267 : {
268 672 : Clear();
269 672 : }
270 :
271 1248 : ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
272 : ScQueryParamBase(r),
273 : ScQueryParamTable(r),
274 1248 : bDestPers(r.bDestPers), nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
275 : {
276 1248 : }
277 :
278 28 : ScQueryParam::ScQueryParam( const ScDBQueryParamInternal& r ) :
279 : ScQueryParamBase(r),
280 : ScQueryParamTable(r),
281 : bDestPers(true),
282 : nDestTab(0),
283 : nDestCol(0),
284 28 : nDestRow(0)
285 : {
286 28 : }
287 :
288 2740 : ScQueryParam::~ScQueryParam()
289 : {
290 2740 : }
291 :
292 672 : void ScQueryParam::Clear()
293 : {
294 672 : nCol1=nCol2 = 0;
295 672 : nRow1=nRow2 = 0;
296 672 : nTab = SCTAB_MAX;
297 672 : bHasHeader = bCaseSens = bRegExp = false;
298 672 : bInplace = bByRow = bDuplicate = true;
299 :
300 672 : boost::ptr_vector<ScQueryEntry>::iterator itr = maEntries.begin(), itrEnd = maEntries.end();
301 6048 : for (; itr != itrEnd; ++itr)
302 5376 : itr->Clear();
303 :
304 672 : ClearDestParams();
305 672 : }
306 :
307 672 : void ScQueryParam::ClearDestParams()
308 : {
309 672 : bDestPers = true;
310 672 : nDestTab = 0;
311 672 : nDestCol = 0;
312 672 : nDestRow = 0;
313 672 : }
314 :
315 417 : ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
316 : {
317 417 : nCol1 = r.nCol1;
318 417 : nRow1 = r.nRow1;
319 417 : nCol2 = r.nCol2;
320 417 : nRow2 = r.nRow2;
321 417 : nTab = r.nTab;
322 417 : nDestTab = r.nDestTab;
323 417 : nDestCol = r.nDestCol;
324 417 : nDestRow = r.nDestRow;
325 417 : bHasHeader = r.bHasHeader;
326 417 : bInplace = r.bInplace;
327 417 : bCaseSens = r.bCaseSens;
328 417 : bRegExp = r.bRegExp;
329 417 : bDuplicate = r.bDuplicate;
330 417 : bByRow = r.bByRow;
331 417 : bDestPers = r.bDestPers;
332 :
333 417 : maEntries = r.maEntries.clone();
334 :
335 417 : return *this;
336 : }
337 :
338 2 : bool ScQueryParam::operator==( const ScQueryParam& rOther ) const
339 : {
340 2 : bool bEqual = false;
341 :
342 : // Anzahl der Queries gleich?
343 2 : SCSIZE nUsed = 0;
344 2 : SCSIZE nOtherUsed = 0;
345 2 : SCSIZE nEntryCount = GetEntryCount();
346 2 : SCSIZE nOtherEntryCount = rOther.GetEntryCount();
347 :
348 2 : while ( nUsed<nEntryCount && maEntries[nUsed].bDoQuery ) ++nUsed;
349 4 : while ( nOtherUsed<nOtherEntryCount && rOther.maEntries[nOtherUsed].bDoQuery )
350 0 : ++nOtherUsed;
351 :
352 2 : if ( (nUsed == nOtherUsed)
353 0 : && (nCol1 == rOther.nCol1)
354 0 : && (nRow1 == rOther.nRow1)
355 0 : && (nCol2 == rOther.nCol2)
356 0 : && (nRow2 == rOther.nRow2)
357 0 : && (nTab == rOther.nTab)
358 0 : && (bHasHeader == rOther.bHasHeader)
359 0 : && (bByRow == rOther.bByRow)
360 0 : && (bInplace == rOther.bInplace)
361 0 : && (bCaseSens == rOther.bCaseSens)
362 0 : && (bRegExp == rOther.bRegExp)
363 0 : && (bDuplicate == rOther.bDuplicate)
364 0 : && (bDestPers == rOther.bDestPers)
365 0 : && (nDestTab == rOther.nDestTab)
366 0 : && (nDestCol == rOther.nDestCol)
367 0 : && (nDestRow == rOther.nDestRow) )
368 : {
369 0 : bEqual = true;
370 0 : for ( SCSIZE i=0; i<nUsed && bEqual; i++ )
371 0 : bEqual = maEntries[i] == rOther.maEntries[i];
372 : }
373 2 : return bEqual;
374 : }
375 :
376 0 : void ScQueryParam::MoveToDest()
377 : {
378 0 : if (!bInplace)
379 : {
380 0 : SCsCOL nDifX = ((SCsCOL) nDestCol) - ((SCsCOL) nCol1);
381 0 : SCsROW nDifY = ((SCsROW) nDestRow) - ((SCsROW) nRow1);
382 0 : SCsTAB nDifZ = ((SCsTAB) nDestTab) - ((SCsTAB) nTab);
383 :
384 0 : nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
385 0 : nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
386 0 : nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
387 0 : nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
388 0 : nTab = sal::static_int_cast<SCTAB>( nTab + nDifZ );
389 0 : size_t n = maEntries.size();
390 0 : for (size_t i=0; i<n; i++)
391 0 : maEntries[i].nField += nDifX;
392 :
393 0 : bInplace = true;
394 : }
395 : else
396 : {
397 : OSL_FAIL("MoveToDest, bInplace == TRUE");
398 : }
399 0 : }
400 :
401 8 : ScDBQueryParamBase::ScDBQueryParamBase(DataType eType) :
402 : ScQueryParamBase(),
403 : mnField(-1),
404 : mbSkipString(true),
405 8 : meType(eType)
406 : {
407 8 : }
408 :
409 8 : ScDBQueryParamBase::~ScDBQueryParamBase()
410 : {
411 8 : }
412 :
413 8 : ScDBQueryParamInternal::ScDBQueryParamInternal() :
414 : ScDBQueryParamBase(ScDBQueryParamBase::INTERNAL),
415 8 : ScQueryParamTable()
416 : {
417 8 : }
418 :
419 16 : ScDBQueryParamInternal::~ScDBQueryParamInternal()
420 : {
421 16 : }
422 :
423 4 : bool ScDBQueryParamInternal::IsValidFieldIndex() const
424 : {
425 4 : return nCol1 <= mnField && mnField <= nCol2;
426 : }
427 :
428 0 : ScDBQueryParamMatrix::ScDBQueryParamMatrix() :
429 0 : ScDBQueryParamBase(ScDBQueryParamBase::MATRIX)
430 : {
431 0 : }
432 :
433 0 : bool ScDBQueryParamMatrix::IsValidFieldIndex() const
434 : {
435 : SCSIZE nC, nR;
436 0 : mpMatrix->GetDimensions(nC, nR);
437 0 : return 0 <= mnField && mnField <= static_cast<SCCOL>(nC);
438 : }
439 :
440 0 : ScDBQueryParamMatrix::~ScDBQueryParamMatrix()
441 : {
442 156 : }
443 :
444 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|