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 "scitems.hxx"
21 : #include <sfx2/objsh.hxx>
22 : #include <svl/itemset.hxx>
23 : #include <svl/zforlist.hxx>
24 : #include <rtl/math.hxx>
25 : #include <unotools/collatorwrapper.hxx>
26 :
27 : #include <com/sun/star/sheet/ConditionOperator2.hpp>
28 :
29 : #include "conditio.hxx"
30 : #include "formulacell.hxx"
31 : #include "document.hxx"
32 : #include "hints.hxx"
33 : #include "compiler.hxx"
34 : #include "rechead.hxx"
35 : #include "rangelst.hxx"
36 : #include "stlpool.hxx"
37 : #include "rangenam.hxx"
38 : #include "colorscale.hxx"
39 : #include "cellvalue.hxx"
40 : #include "editutil.hxx"
41 : #include "tokenarray.hxx"
42 : #include "refupdatecontext.hxx"
43 : #include "svl/sharedstring.hxx"
44 :
45 : using namespace formula;
46 :
47 :
48 0 : ScFormatEntry::ScFormatEntry(ScDocument* pDoc):
49 0 : mpDoc(pDoc)
50 : {
51 0 : }
52 :
53 0 : bool ScFormatEntry::operator==( const ScFormatEntry& r ) const
54 : {
55 0 : if(GetType() != r.GetType())
56 0 : return false;
57 :
58 0 : switch(GetType())
59 : {
60 : case condformat::CONDITION:
61 0 : return static_cast<const ScCondFormatEntry&>(*this) == static_cast<const ScCondFormatEntry&>(r);
62 : default:
63 : // TODO: implement also this case
64 : // actually return false for these cases is not that bad
65 : // as soon as databar and color scale are tested we need
66 : // to think about the range
67 0 : return false;
68 : }
69 : }
70 :
71 0 : void ScFormatEntry::startRendering()
72 : {
73 0 : }
74 :
75 0 : void ScFormatEntry::endRendering()
76 : {
77 0 : }
78 :
79 0 : static bool lcl_HasRelRef( ScDocument* pDoc, ScTokenArray* pFormula, sal_uInt16 nRecursion = 0 )
80 : {
81 0 : if (pFormula)
82 : {
83 0 : pFormula->Reset();
84 : FormulaToken* t;
85 0 : for( t = pFormula->Next(); t; t = pFormula->Next() )
86 : {
87 0 : switch( t->GetType() )
88 : {
89 : case svDoubleRef:
90 : {
91 0 : ScSingleRefData& rRef2 = static_cast<ScToken*>(t)->GetDoubleRef().Ref2;
92 0 : if ( rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel() )
93 0 : return true;
94 : }
95 : // fall through
96 :
97 : case svSingleRef:
98 : {
99 0 : ScSingleRefData& rRef1 = static_cast<ScToken*>(t)->GetSingleRef();
100 0 : if ( rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel() )
101 0 : return true;
102 : }
103 0 : break;
104 :
105 : case svIndex:
106 : {
107 0 : if( t->GetOpCode() == ocName ) // DB areas always absolute
108 0 : if( ScRangeData* pRangeData = pDoc->GetRangeName()->findByIndex( t->GetIndex() ) )
109 0 : if( (nRecursion < 42) && lcl_HasRelRef( pDoc, pRangeData->GetCode(), nRecursion + 1 ) )
110 0 : return true;
111 : }
112 0 : break;
113 :
114 : // #i34474# function result dependent on cell position
115 : case svByte:
116 : {
117 0 : switch( t->GetOpCode() )
118 : {
119 : case ocRow: // ROW() returns own row index
120 : case ocColumn: // COLUMN() returns own column index
121 : case ocTable: // SHEET() returns own sheet index
122 : case ocCell: // CELL() may return own cell address
123 0 : return true;
124 : // break;
125 : default:
126 : {
127 : // added to avoid warnings
128 : }
129 : }
130 : }
131 0 : break;
132 :
133 : default:
134 : {
135 : // added to avoid warnings
136 : }
137 : }
138 : }
139 : }
140 0 : return false;
141 : }
142 :
143 0 : ScConditionEntry::ScConditionEntry( const ScConditionEntry& r ) :
144 : ScFormatEntry(r.mpDoc),
145 : eOp(r.eOp),
146 : nOptions(r.nOptions),
147 : nVal1(r.nVal1),
148 : nVal2(r.nVal2),
149 : aStrVal1(r.aStrVal1),
150 : aStrVal2(r.aStrVal2),
151 : aStrNmsp1(r.aStrNmsp1),
152 : aStrNmsp2(r.aStrNmsp2),
153 : eTempGrammar1(r.eTempGrammar1),
154 : eTempGrammar2(r.eTempGrammar2),
155 : bIsStr1(r.bIsStr1),
156 : bIsStr2(r.bIsStr2),
157 : pFormula1(NULL),
158 : pFormula2(NULL),
159 : aSrcPos(r.aSrcPos),
160 : aSrcString(r.aSrcString),
161 : pFCell1(NULL),
162 : pFCell2(NULL),
163 : bRelRef1(r.bRelRef1),
164 : bRelRef2(r.bRelRef2),
165 : bFirstRun(true),
166 0 : pCondFormat(r.pCondFormat)
167 : {
168 : // ScTokenArray copy ctor erzeugt flache Kopie
169 :
170 0 : if (r.pFormula1)
171 0 : pFormula1 = new ScTokenArray( *r.pFormula1 );
172 0 : if (r.pFormula2)
173 0 : pFormula2 = new ScTokenArray( *r.pFormula2 );
174 :
175 : // Formelzellen werden erst bei IsValid angelegt
176 0 : }
177 :
178 0 : ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntry& r ) :
179 : ScFormatEntry(pDocument),
180 : eOp(r.eOp),
181 : nOptions(r.nOptions),
182 : nVal1(r.nVal1),
183 : nVal2(r.nVal2),
184 : aStrVal1(r.aStrVal1),
185 : aStrVal2(r.aStrVal2),
186 : aStrNmsp1(r.aStrNmsp1),
187 : aStrNmsp2(r.aStrNmsp2),
188 : eTempGrammar1(r.eTempGrammar1),
189 : eTempGrammar2(r.eTempGrammar2),
190 : bIsStr1(r.bIsStr1),
191 : bIsStr2(r.bIsStr2),
192 : pFormula1(NULL),
193 : pFormula2(NULL),
194 : aSrcPos(r.aSrcPos),
195 : aSrcString(r.aSrcString),
196 : pFCell1(NULL),
197 : pFCell2(NULL),
198 : bRelRef1(r.bRelRef1),
199 : bRelRef2(r.bRelRef2),
200 : bFirstRun(true),
201 0 : pCondFormat(r.pCondFormat)
202 : {
203 : // echte Kopie der Formeln (fuer Ref-Undo)
204 :
205 0 : if (r.pFormula1)
206 0 : pFormula1 = r.pFormula1->Clone();
207 0 : if (r.pFormula2)
208 0 : pFormula2 = r.pFormula2->Clone();
209 :
210 : // Formelzellen werden erst bei IsValid angelegt
211 : //! im Clipboard nicht - dann vorher interpretieren !!!
212 0 : }
213 :
214 0 : ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
215 : const OUString& rExpr1, const OUString& rExpr2, ScDocument* pDocument, const ScAddress& rPos,
216 : const OUString& rExprNmsp1, const OUString& rExprNmsp2,
217 : FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2 ) :
218 : ScFormatEntry(pDocument),
219 : eOp(eOper),
220 : nOptions(0),
221 : nVal1(0.0),
222 : nVal2(0.0),
223 : aStrNmsp1(rExprNmsp1),
224 : aStrNmsp2(rExprNmsp2),
225 : eTempGrammar1(eGrammar1),
226 : eTempGrammar2(eGrammar2),
227 : bIsStr1(false),
228 : bIsStr2(false),
229 : pFormula1(NULL),
230 : pFormula2(NULL),
231 : aSrcPos(rPos),
232 : pFCell1(NULL),
233 : pFCell2(NULL),
234 : bRelRef1(false),
235 : bRelRef2(false),
236 : bFirstRun(true),
237 0 : pCondFormat(NULL)
238 : {
239 0 : Compile( rExpr1, rExpr2, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2, false );
240 :
241 : // Formelzellen werden erst bei IsValid angelegt
242 0 : }
243 :
244 0 : ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
245 : const ScTokenArray* pArr1, const ScTokenArray* pArr2,
246 : ScDocument* pDocument, const ScAddress& rPos ) :
247 : ScFormatEntry(pDocument),
248 : eOp(eOper),
249 : nOptions(0),
250 : nVal1(0.0),
251 : nVal2(0.0),
252 : eTempGrammar1(FormulaGrammar::GRAM_DEFAULT),
253 : eTempGrammar2(FormulaGrammar::GRAM_DEFAULT),
254 : bIsStr1(false),
255 : bIsStr2(false),
256 : pFormula1(NULL),
257 : pFormula2(NULL),
258 : aSrcPos(rPos),
259 : pFCell1(NULL),
260 : pFCell2(NULL),
261 : bRelRef1(false),
262 : bRelRef2(false),
263 : bFirstRun(true),
264 0 : pCondFormat(NULL)
265 : {
266 0 : if ( pArr1 )
267 : {
268 0 : pFormula1 = new ScTokenArray( *pArr1 );
269 0 : if ( pFormula1->GetLen() == 1 )
270 : {
271 : // einzelne (konstante Zahl) ?
272 0 : FormulaToken* pToken = pFormula1->First();
273 0 : if ( pToken->GetOpCode() == ocPush )
274 : {
275 0 : if ( pToken->GetType() == svDouble )
276 : {
277 0 : nVal1 = pToken->GetDouble();
278 0 : DELETEZ(pFormula1); // nicht als Formel merken
279 : }
280 0 : else if ( pToken->GetType() == svString )
281 : {
282 0 : bIsStr1 = true;
283 0 : aStrVal1 = pToken->GetString().getString();
284 0 : DELETEZ(pFormula1); // nicht als Formel merken
285 : }
286 : }
287 : }
288 0 : bRelRef1 = lcl_HasRelRef( mpDoc, pFormula1 );
289 : }
290 0 : if ( pArr2 )
291 : {
292 0 : pFormula2 = new ScTokenArray( *pArr2 );
293 0 : if ( pFormula2->GetLen() == 1 )
294 : {
295 : // einzelne (konstante Zahl) ?
296 0 : FormulaToken* pToken = pFormula2->First();
297 0 : if ( pToken->GetOpCode() == ocPush )
298 : {
299 0 : if ( pToken->GetType() == svDouble )
300 : {
301 0 : nVal2 = pToken->GetDouble();
302 0 : DELETEZ(pFormula2); // nicht als Formel merken
303 : }
304 0 : else if ( pToken->GetType() == svString )
305 : {
306 0 : bIsStr2 = true;
307 0 : aStrVal2 = pToken->GetString().getString();
308 0 : DELETEZ(pFormula2); // nicht als Formel merken
309 : }
310 : }
311 : }
312 0 : bRelRef2 = lcl_HasRelRef( mpDoc, pFormula2 );
313 : }
314 :
315 : // formula cells are created at IsValid
316 0 : }
317 :
318 0 : ScConditionEntry::~ScConditionEntry()
319 : {
320 0 : delete pFCell1;
321 0 : delete pFCell2;
322 :
323 0 : delete pFormula1;
324 0 : delete pFormula2;
325 0 : }
326 :
327 0 : void ScConditionEntry::Compile( const OUString& rExpr1, const OUString& rExpr2,
328 : const OUString& rExprNmsp1, const OUString& rExprNmsp2,
329 : FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2, bool bTextToReal )
330 : {
331 0 : if ( !rExpr1.isEmpty() || !rExpr2.isEmpty() )
332 : {
333 0 : ScCompiler aComp( mpDoc, aSrcPos );
334 :
335 0 : if ( !rExpr1.isEmpty() )
336 : {
337 0 : aComp.SetGrammar( eGrammar1 );
338 0 : if ( mpDoc->IsImportingXML() && !bTextToReal )
339 : {
340 : // temporary formula string as string tokens
341 : //! merge with lcl_ScDocFunc_CreateTokenArrayXML
342 0 : pFormula1 = new ScTokenArray;
343 0 : pFormula1->AddStringXML( rExpr1 );
344 : // bRelRef1 is set when the formula is compiled again (CompileXML)
345 : }
346 : else
347 : {
348 0 : pFormula1 = aComp.CompileString( rExpr1, rExprNmsp1 );
349 0 : if ( pFormula1->GetLen() == 1 )
350 : {
351 : // einzelne (konstante Zahl) ?
352 0 : FormulaToken* pToken = pFormula1->First();
353 0 : if ( pToken->GetOpCode() == ocPush )
354 : {
355 0 : if ( pToken->GetType() == svDouble )
356 : {
357 0 : nVal1 = pToken->GetDouble();
358 0 : DELETEZ(pFormula1); // nicht als Formel merken
359 : }
360 0 : else if ( pToken->GetType() == svString )
361 : {
362 0 : bIsStr1 = true;
363 0 : aStrVal1 = pToken->GetString().getString();
364 0 : DELETEZ(pFormula1); // nicht als Formel merken
365 : }
366 : }
367 : }
368 0 : bRelRef1 = lcl_HasRelRef( mpDoc, pFormula1 );
369 : }
370 : }
371 :
372 0 : if ( !rExpr2.isEmpty() )
373 : {
374 0 : aComp.SetGrammar( eGrammar2 );
375 0 : if ( mpDoc->IsImportingXML() && !bTextToReal )
376 : {
377 : // temporary formula string as string tokens
378 : //! merge with lcl_ScDocFunc_CreateTokenArrayXML
379 0 : pFormula2 = new ScTokenArray;
380 0 : pFormula2->AddStringXML( rExpr2 );
381 : // bRelRef2 is set when the formula is compiled again (CompileXML)
382 : }
383 : else
384 : {
385 0 : pFormula2 = aComp.CompileString( rExpr2, rExprNmsp2 );
386 0 : if ( pFormula2->GetLen() == 1 )
387 : {
388 : // einzelne (konstante Zahl) ?
389 0 : FormulaToken* pToken = pFormula2->First();
390 0 : if ( pToken->GetOpCode() == ocPush )
391 : {
392 0 : if ( pToken->GetType() == svDouble )
393 : {
394 0 : nVal2 = pToken->GetDouble();
395 0 : DELETEZ(pFormula2); // nicht als Formel merken
396 : }
397 0 : else if ( pToken->GetType() == svString )
398 : {
399 0 : bIsStr2 = true;
400 0 : aStrVal2 = pToken->GetString().getString();
401 0 : DELETEZ(pFormula2); // nicht als Formel merken
402 : }
403 : }
404 : }
405 0 : bRelRef2 = lcl_HasRelRef( mpDoc, pFormula2 );
406 : }
407 0 : }
408 : }
409 0 : }
410 :
411 0 : void ScConditionEntry::MakeCells( const ScAddress& rPos ) // Formelzellen anlegen
412 : {
413 0 : if ( !mpDoc->IsClipOrUndo() ) // nie im Clipboard rechnen!
414 : {
415 0 : if ( pFormula1 && !pFCell1 && !bRelRef1 )
416 : {
417 0 : pFCell1 = new ScFormulaCell(mpDoc, rPos, *pFormula1);
418 0 : pFCell1->StartListeningTo( mpDoc );
419 : }
420 :
421 0 : if ( pFormula2 && !pFCell2 && !bRelRef2 )
422 : {
423 0 : pFCell2 = new ScFormulaCell(mpDoc, rPos, *pFormula2);
424 0 : pFCell2->StartListeningTo( mpDoc );
425 : }
426 : }
427 0 : }
428 :
429 0 : void ScConditionEntry::SetIgnoreBlank(bool bSet)
430 : {
431 : // Das Bit SC_COND_NOBLANKS wird gesetzt, wenn Blanks nicht ignoriert werden
432 : // (nur bei Gueltigkeit)
433 :
434 0 : if (bSet)
435 0 : nOptions &= ~SC_COND_NOBLANKS;
436 : else
437 0 : nOptions |= SC_COND_NOBLANKS;
438 0 : }
439 :
440 0 : void ScConditionEntry::CompileAll()
441 : {
442 : // Formelzellen loeschen, dann wird beim naechsten IsValid neu kompiliert
443 :
444 0 : DELETEZ(pFCell1);
445 0 : DELETEZ(pFCell2);
446 0 : }
447 :
448 0 : void ScConditionEntry::CompileXML()
449 : {
450 : // First parse the formula source position if it was stored as text
451 :
452 0 : if ( !aSrcString.isEmpty() )
453 : {
454 0 : ScAddress aNew;
455 : /* XML is always in OOo:A1 format, although R1C1 would be more amenable
456 : * to compression */
457 0 : if ( aNew.Parse( aSrcString, mpDoc ) & SCA_VALID )
458 0 : aSrcPos = aNew;
459 : // if the position is invalid, there isn't much we can do at this time
460 0 : aSrcString = OUString();
461 : }
462 :
463 : // Convert the text tokens that were created during XML import into real tokens.
464 :
465 : Compile( GetExpression(aSrcPos, 0, 0, eTempGrammar1),
466 : GetExpression(aSrcPos, 1, 0, eTempGrammar2),
467 0 : aStrNmsp1, aStrNmsp2, eTempGrammar1, eTempGrammar2, true );
468 0 : }
469 :
470 0 : void ScConditionEntry::SetSrcString( const OUString& rNew )
471 : {
472 : // aSrcString is only evaluated in CompileXML
473 : SAL_WARN_IF( !mpDoc->IsImportingXML(), "sc", "SetSrcString is only valid for XML import" );
474 :
475 0 : aSrcString = rNew;
476 0 : }
477 :
478 0 : void ScConditionEntry::SetFormula1( const ScTokenArray& rArray )
479 : {
480 0 : DELETEZ( pFormula1 );
481 0 : if( rArray.GetLen() > 0 )
482 : {
483 0 : pFormula1 = new ScTokenArray( rArray );
484 0 : bRelRef1 = lcl_HasRelRef( mpDoc, pFormula1 );
485 : }
486 0 : }
487 :
488 0 : void ScConditionEntry::SetFormula2( const ScTokenArray& rArray )
489 : {
490 0 : DELETEZ( pFormula2 );
491 0 : if( rArray.GetLen() > 0 )
492 : {
493 0 : pFormula2 = new ScTokenArray( rArray );
494 0 : bRelRef2 = lcl_HasRelRef( mpDoc, pFormula2 );
495 : }
496 0 : }
497 :
498 0 : void ScConditionEntry::UpdateReference( sc::RefUpdateContext& rCxt )
499 : {
500 0 : if(pCondFormat)
501 0 : aSrcPos = pCondFormat->GetRange().Combine().aStart;
502 0 : ScAddress aOldSrcPos = aSrcPos;
503 0 : bool bChangedPos = false;
504 0 : if (rCxt.meMode == URM_INSDEL && rCxt.maRange.In(aSrcPos))
505 : {
506 0 : aSrcPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
507 0 : bChangedPos = aSrcPos != aOldSrcPos;
508 : }
509 :
510 0 : if (pFormula1)
511 : {
512 0 : sc::RefUpdateResult aRes = pFormula1->AdjustReferenceInName(rCxt, aOldSrcPos);
513 0 : if (aRes.mbReferenceModified || bChangedPos)
514 0 : DELETEZ(pFCell1); // is created again in IsValid
515 : }
516 0 : if (pFormula2)
517 : {
518 0 : sc::RefUpdateResult aRes = pFormula2->AdjustReferenceInName(rCxt, aOldSrcPos);
519 0 : if (aRes.mbReferenceModified || bChangedPos)
520 0 : DELETEZ(pFCell2); // is created again in IsValid
521 : }
522 0 : }
523 :
524 0 : void ScConditionEntry::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt )
525 : {
526 0 : if (pFormula1)
527 : {
528 0 : pFormula1->AdjustReferenceOnInsertedTab(rCxt, aSrcPos);
529 0 : DELETEZ(pFCell1);
530 : }
531 :
532 0 : if (pFormula2)
533 : {
534 0 : pFormula2->AdjustReferenceOnInsertedTab(rCxt, aSrcPos);
535 0 : DELETEZ(pFCell2);
536 : }
537 0 : }
538 :
539 0 : void ScConditionEntry::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt )
540 : {
541 0 : if (pFormula1)
542 : {
543 0 : pFormula1->AdjustReferenceOnDeletedTab(rCxt, aSrcPos);
544 0 : DELETEZ(pFCell1);
545 : }
546 :
547 0 : if (pFormula2)
548 : {
549 0 : pFormula2->AdjustReferenceOnDeletedTab(rCxt, aSrcPos);
550 0 : DELETEZ(pFCell2);
551 : }
552 0 : }
553 :
554 0 : void ScConditionEntry::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt )
555 : {
556 0 : if (pFormula1)
557 : {
558 0 : pFormula1->AdjustReferenceOnMovedTab(rCxt, aSrcPos);
559 0 : DELETEZ(pFCell1);
560 : }
561 :
562 0 : if (pFormula2)
563 : {
564 0 : pFormula2->AdjustReferenceOnMovedTab(rCxt, aSrcPos);
565 0 : DELETEZ(pFCell2);
566 : }
567 0 : }
568 :
569 : //! als Vergleichsoperator ans TokenArray ???
570 :
571 0 : static bool lcl_IsEqual( const ScTokenArray* pArr1, const ScTokenArray* pArr2 )
572 : {
573 : // verglichen wird nur das nicht-RPN Array
574 :
575 0 : if ( pArr1 && pArr2 )
576 : {
577 0 : sal_uInt16 nLen = pArr1->GetLen();
578 0 : if ( pArr2->GetLen() != nLen )
579 0 : return false;
580 :
581 0 : FormulaToken** ppToken1 = pArr1->GetArray();
582 0 : FormulaToken** ppToken2 = pArr2->GetArray();
583 0 : for (sal_uInt16 i=0; i<nLen; i++)
584 : {
585 0 : if ( ppToken1[i] != ppToken2[i] &&
586 0 : !(*ppToken1[i] == *ppToken2[i]) )
587 0 : return false; // Unterschied
588 : }
589 0 : return true; // alle Eintraege gleich
590 : }
591 : else
592 0 : return !pArr1 && !pArr2; // beide 0 -> gleich
593 : }
594 :
595 0 : bool ScConditionEntry::operator== ( const ScConditionEntry& r ) const
596 : {
597 0 : bool bEq = (eOp == r.eOp && nOptions == r.nOptions &&
598 0 : lcl_IsEqual( pFormula1, r.pFormula1 ) &&
599 0 : lcl_IsEqual( pFormula2, r.pFormula2 ));
600 0 : if (bEq)
601 : {
602 : // for formulas, the reference positions must be compared, too
603 : // (including aSrcString, for inserting the entries during XML import)
604 0 : if ( ( pFormula1 || pFormula2 ) && ( aSrcPos != r.aSrcPos || aSrcString != r.aSrcString ) )
605 0 : bEq = false;
606 :
607 : // wenn keine Formeln, Werte vergleichen
608 0 : if ( !pFormula1 && ( nVal1 != r.nVal1 || aStrVal1 != r.aStrVal1 || bIsStr1 != r.bIsStr1 ) )
609 0 : bEq = false;
610 0 : if ( !pFormula2 && ( nVal2 != r.nVal2 || aStrVal2 != r.aStrVal2 || bIsStr2 != r.bIsStr2 ) )
611 0 : bEq = false;
612 : }
613 :
614 0 : return bEq;
615 : }
616 :
617 0 : void ScConditionEntry::Interpret( const ScAddress& rPos )
618 : {
619 : // Formelzellen anlegen
620 : // dabei koennen neue Broadcaster (Note-Zellen) ins Dokument eingefuegt werden !!!!
621 :
622 0 : if ( ( pFormula1 && !pFCell1 ) || ( pFormula2 && !pFCell2 ) )
623 0 : MakeCells( rPos );
624 :
625 : // Formeln auswerten
626 :
627 0 : bool bDirty = false; //! 1 und 2 getrennt ???
628 :
629 0 : ScFormulaCell* pTemp1 = NULL;
630 0 : ScFormulaCell* pEff1 = pFCell1;
631 0 : if ( bRelRef1 )
632 : {
633 0 : pTemp1 = pFormula1 ? new ScFormulaCell(mpDoc, rPos, *pFormula1) : new ScFormulaCell(mpDoc, rPos);
634 0 : pEff1 = pTemp1;
635 : }
636 0 : if ( pEff1 )
637 : {
638 0 : if (!pEff1->IsRunning()) // keine 522 erzeugen
639 : {
640 : //! Changed statt Dirty abfragen !!!
641 0 : if (pEff1->GetDirty() && !bRelRef1 && mpDoc->GetAutoCalc())
642 0 : bDirty = true;
643 0 : if (pEff1->IsValue())
644 : {
645 0 : bIsStr1 = false;
646 0 : nVal1 = pEff1->GetValue();
647 0 : aStrVal1 = OUString();
648 : }
649 : else
650 : {
651 0 : bIsStr1 = true;
652 0 : aStrVal1 = pEff1->GetString().getString();
653 0 : nVal1 = 0.0;
654 : }
655 : }
656 : }
657 0 : delete pTemp1;
658 :
659 0 : ScFormulaCell* pTemp2 = NULL;
660 0 : ScFormulaCell* pEff2 = pFCell2; //@ 1!=2
661 0 : if ( bRelRef2 )
662 : {
663 0 : pTemp2 = pFormula2 ? new ScFormulaCell(mpDoc, rPos, *pFormula2) : new ScFormulaCell(mpDoc, rPos);
664 0 : pEff2 = pTemp2;
665 : }
666 0 : if ( pEff2 )
667 : {
668 0 : if (!pEff2->IsRunning()) // keine 522 erzeugen
669 : {
670 0 : if (pEff2->GetDirty() && !bRelRef2 && mpDoc->GetAutoCalc())
671 0 : bDirty = true;
672 0 : if (pEff2->IsValue())
673 : {
674 0 : bIsStr2 = false;
675 0 : nVal2 = pEff2->GetValue();
676 0 : aStrVal2 = OUString();
677 : }
678 : else
679 : {
680 0 : bIsStr2 = true;
681 0 : aStrVal2 = pEff2->GetString().getString();
682 0 : nVal2 = 0.0;
683 : }
684 : }
685 : }
686 0 : delete pTemp2;
687 :
688 : // wenn IsRunning, bleiben die letzten Werte erhalten
689 :
690 0 : if (bDirty && !bFirstRun)
691 : {
692 : // bei bedingten Formaten neu painten
693 :
694 0 : DataChanged( NULL ); // alles
695 : }
696 :
697 0 : bFirstRun = false;
698 0 : }
699 :
700 0 : static bool lcl_GetCellContent( ScRefCellValue& rCell, bool bIsStr1, double& rArg, OUString& rArgStr,
701 : const ScDocument* pDoc )
702 : {
703 :
704 0 : if (rCell.isEmpty())
705 0 : return !bIsStr1;
706 :
707 0 : bool bVal = true;
708 :
709 0 : switch (rCell.meType)
710 : {
711 : case CELLTYPE_VALUE:
712 0 : rArg = rCell.mfValue;
713 0 : break;
714 : case CELLTYPE_FORMULA:
715 : {
716 0 : bVal = rCell.mpFormula->IsValue();
717 0 : if (bVal)
718 0 : rArg = rCell.mpFormula->GetValue();
719 : else
720 0 : rArgStr = rCell.mpFormula->GetString().getString();
721 : }
722 0 : break;
723 : case CELLTYPE_STRING:
724 : case CELLTYPE_EDIT:
725 0 : bVal = false;
726 0 : if (rCell.meType == CELLTYPE_STRING)
727 0 : rArgStr = rCell.mpString->getString();
728 0 : else if (rCell.mpEditText)
729 0 : rArgStr = ScEditUtil::GetString(*rCell.mpEditText, pDoc);
730 0 : break;
731 : default:
732 : ;
733 : }
734 :
735 0 : return bVal;
736 : }
737 :
738 0 : void ScConditionEntry::FillCache() const
739 : {
740 0 : if(!mpCache)
741 : {
742 0 : const ScRangeList& rRanges = pCondFormat->GetRange();
743 0 : mpCache.reset(new ScConditionEntryCache);
744 0 : size_t nListCount = rRanges.size();
745 0 : for( size_t i = 0; i < nListCount; i++ )
746 : {
747 0 : const ScRange *aRange = rRanges[i];
748 0 : SCROW nRow = aRange->aEnd.Row();
749 0 : SCCOL nCol = aRange->aEnd.Col();
750 0 : SCCOL nColStart = aRange->aStart.Col();
751 0 : SCROW nRowStart = aRange->aStart.Row();
752 0 : SCTAB nTab = aRange->aStart.Tab();
753 :
754 : // temporary fix to workaorund slow duplicate entry
755 : // conditions, prevent to use a whole row
756 0 : if(nRow == MAXROW)
757 : {
758 0 : bool bShrunk = false;
759 : mpDoc->ShrinkToUsedDataArea(bShrunk, nTab, nColStart, nRowStart,
760 0 : nCol, nRow, false);
761 : }
762 :
763 0 : for( SCROW r = nRowStart; r <= nRow; r++ )
764 0 : for( SCCOL c = nColStart; c <= nCol; c++ )
765 : {
766 0 : ScRefCellValue aCell;
767 0 : aCell.assign(*mpDoc, ScAddress(c, r, nTab));
768 0 : if (aCell.isEmpty())
769 0 : continue;
770 :
771 0 : double nVal = 0.0;
772 0 : OUString aStr;
773 0 : if (!lcl_GetCellContent(aCell, false, nVal, aStr, mpDoc))
774 : {
775 : std::pair<ScConditionEntryCache::StringCacheType::iterator, bool> aResult =
776 0 : mpCache->maStrings.insert(
777 0 : ScConditionEntryCache::StringCacheType::value_type(aStr, 1));
778 :
779 0 : if(!aResult.second)
780 0 : aResult.first->second++;
781 : }
782 : else
783 : {
784 : std::pair<ScConditionEntryCache::ValueCacheType::iterator, bool> aResult =
785 0 : mpCache->maValues.insert(
786 0 : ScConditionEntryCache::ValueCacheType::value_type(nVal, 1));
787 :
788 0 : if(!aResult.second)
789 0 : aResult.first->second++;
790 :
791 0 : ++(mpCache->nValueItems);
792 : }
793 0 : }
794 : }
795 : }
796 0 : }
797 :
798 0 : bool ScConditionEntry::IsDuplicate( double nArg, const OUString& rStr ) const
799 : {
800 0 : FillCache();
801 :
802 0 : if(rStr.isEmpty())
803 : {
804 0 : ScConditionEntryCache::ValueCacheType::iterator itr = mpCache->maValues.find(nArg);
805 0 : if(itr == mpCache->maValues.end())
806 0 : return false;
807 : else
808 : {
809 0 : if(itr->second > 1)
810 0 : return true;
811 : else
812 0 : return false;
813 : }
814 : }
815 : else
816 : {
817 0 : ScConditionEntryCache::StringCacheType::iterator itr = mpCache->maStrings.find(rStr);
818 0 : if(itr == mpCache->maStrings.end())
819 0 : return false;
820 : else
821 : {
822 0 : if(itr->second > 1)
823 0 : return true;
824 : else
825 0 : return false;
826 : }
827 : }
828 : }
829 :
830 0 : bool ScConditionEntry::IsTopNElement( double nArg ) const
831 : {
832 0 : FillCache();
833 :
834 0 : if(mpCache->nValueItems <= nVal1)
835 0 : return true;
836 :
837 0 : size_t nCells = 0;
838 0 : for(ScConditionEntryCache::ValueCacheType::const_reverse_iterator itr = mpCache->maValues.rbegin(),
839 0 : itrEnd = mpCache->maValues.rend(); itr != itrEnd; ++itr)
840 : {
841 0 : if(nCells >= nVal1)
842 0 : return false;
843 0 : if(itr->first <= nArg)
844 0 : return true;
845 0 : nCells += itr->second;
846 : }
847 :
848 0 : return true;
849 : }
850 :
851 0 : bool ScConditionEntry::IsBottomNElement( double nArg ) const
852 : {
853 0 : FillCache();
854 :
855 0 : if(mpCache->nValueItems <= nVal1)
856 0 : return true;
857 :
858 0 : size_t nCells = 0;
859 0 : for(ScConditionEntryCache::ValueCacheType::const_iterator itr = mpCache->maValues.begin(),
860 0 : itrEnd = mpCache->maValues.end(); itr != itrEnd; ++itr)
861 : {
862 0 : if(nCells >= nVal1)
863 0 : return false;
864 0 : if(itr->first >= nArg)
865 0 : return true;
866 0 : nCells += itr->second;
867 : }
868 :
869 0 : return true;
870 : }
871 :
872 0 : bool ScConditionEntry::IsTopNPercent( double nArg ) const
873 : {
874 0 : FillCache();
875 :
876 0 : size_t nCells = 0;
877 0 : size_t nLimitCells = static_cast<size_t>(mpCache->nValueItems*nVal1/100);
878 0 : for(ScConditionEntryCache::ValueCacheType::const_reverse_iterator itr = mpCache->maValues.rbegin(),
879 0 : itrEnd = mpCache->maValues.rend(); itr != itrEnd; ++itr)
880 : {
881 0 : if(nCells >= nLimitCells)
882 0 : return false;
883 0 : if(itr->first <= nArg)
884 0 : return true;
885 0 : nCells += itr->second;
886 : }
887 :
888 0 : return true;
889 : }
890 :
891 0 : bool ScConditionEntry::IsBottomNPercent( double nArg ) const
892 : {
893 0 : FillCache();
894 :
895 0 : size_t nCells = 0;
896 0 : size_t nLimitCells = static_cast<size_t>(mpCache->nValueItems*nVal1/100);
897 0 : for(ScConditionEntryCache::ValueCacheType::const_iterator itr = mpCache->maValues.begin(),
898 0 : itrEnd = mpCache->maValues.end(); itr != itrEnd; ++itr)
899 : {
900 0 : if(nCells >= nLimitCells)
901 0 : return false;
902 0 : if(itr->first >= nArg)
903 0 : return true;
904 0 : nCells += itr->second;
905 : }
906 :
907 0 : return true;
908 : }
909 :
910 0 : bool ScConditionEntry::IsBelowAverage( double nArg, bool bEqual ) const
911 : {
912 0 : FillCache();
913 :
914 0 : double nSum = 0;
915 0 : for(ScConditionEntryCache::ValueCacheType::const_iterator itr = mpCache->maValues.begin(),
916 0 : itrEnd = mpCache->maValues.end(); itr != itrEnd; ++itr)
917 : {
918 0 : nSum += itr->first * itr->second;
919 : }
920 :
921 0 : if(bEqual)
922 0 : return (nArg <= nSum/mpCache->nValueItems);
923 : else
924 0 : return (nArg < nSum/mpCache->nValueItems);
925 : }
926 :
927 0 : bool ScConditionEntry::IsAboveAverage( double nArg, bool bEqual ) const
928 : {
929 0 : FillCache();
930 :
931 0 : double nSum = 0;
932 0 : for(ScConditionEntryCache::ValueCacheType::const_iterator itr = mpCache->maValues.begin(),
933 0 : itrEnd = mpCache->maValues.end(); itr != itrEnd; ++itr)
934 : {
935 0 : nSum += itr->first * itr->second;
936 : }
937 :
938 0 : if(bEqual)
939 0 : return (nArg >= nSum/mpCache->nValueItems);
940 : else
941 0 : return (nArg > nSum/mpCache->nValueItems);
942 : }
943 :
944 0 : bool ScConditionEntry::IsError( const ScAddress& rPos ) const
945 : {
946 0 : switch (mpDoc->GetCellType(rPos))
947 : {
948 : case CELLTYPE_VALUE:
949 0 : return false;
950 : case CELLTYPE_FORMULA:
951 : {
952 0 : ScFormulaCell* pFormulaCell = const_cast<ScFormulaCell*>(mpDoc->GetFormulaCell(rPos));
953 0 : if (pFormulaCell && pFormulaCell->GetErrCode())
954 0 : return true;
955 : }
956 : case CELLTYPE_STRING:
957 : case CELLTYPE_EDIT:
958 0 : return false;
959 : default:
960 0 : break;
961 : }
962 0 : return false;
963 : }
964 :
965 0 : bool ScConditionEntry::IsValid( double nArg, const ScAddress& rPos ) const
966 : {
967 : // Interpret muss schon gerufen sein
968 :
969 0 : if ( bIsStr1 )
970 : {
971 0 : switch( eOp )
972 : {
973 : case SC_COND_BEGINS_WITH:
974 : case SC_COND_ENDS_WITH:
975 : case SC_COND_CONTAINS_TEXT:
976 : case SC_COND_NOT_CONTAINS_TEXT:
977 0 : break;
978 : case SC_COND_NOTEQUAL:
979 0 : return true;
980 : default:
981 0 : return false;
982 : }
983 : }
984 :
985 0 : if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
986 0 : if ( bIsStr2 )
987 0 : return false;
988 :
989 0 : double nComp1 = nVal1; // Kopie, damit vertauscht werden kann
990 0 : double nComp2 = nVal2;
991 :
992 0 : if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
993 0 : if ( nComp1 > nComp2 )
994 : {
995 : // richtige Reihenfolge fuer Wertebereich
996 0 : double nTemp = nComp1; nComp1 = nComp2; nComp2 = nTemp;
997 : }
998 :
999 : // Alle Grenzfaelle muessen per ::rtl::math::approxEqual getestet werden!
1000 :
1001 0 : bool bValid = false;
1002 0 : switch (eOp)
1003 : {
1004 : case SC_COND_NONE:
1005 0 : break; // immer sal_False;
1006 : case SC_COND_EQUAL:
1007 0 : bValid = ::rtl::math::approxEqual( nArg, nComp1 );
1008 0 : break;
1009 : case SC_COND_NOTEQUAL:
1010 0 : bValid = !::rtl::math::approxEqual( nArg, nComp1 );
1011 0 : break;
1012 : case SC_COND_GREATER:
1013 0 : bValid = ( nArg > nComp1 ) && !::rtl::math::approxEqual( nArg, nComp1 );
1014 0 : break;
1015 : case SC_COND_EQGREATER:
1016 0 : bValid = ( nArg >= nComp1 ) || ::rtl::math::approxEqual( nArg, nComp1 );
1017 0 : break;
1018 : case SC_COND_LESS:
1019 0 : bValid = ( nArg < nComp1 ) && !::rtl::math::approxEqual( nArg, nComp1 );
1020 0 : break;
1021 : case SC_COND_EQLESS:
1022 0 : bValid = ( nArg <= nComp1 ) || ::rtl::math::approxEqual( nArg, nComp1 );
1023 0 : break;
1024 : case SC_COND_BETWEEN:
1025 0 : bValid = ( nArg >= nComp1 && nArg <= nComp2 ) ||
1026 0 : ::rtl::math::approxEqual( nArg, nComp1 ) || ::rtl::math::approxEqual( nArg, nComp2 );
1027 0 : break;
1028 : case SC_COND_NOTBETWEEN:
1029 0 : bValid = ( nArg < nComp1 || nArg > nComp2 ) &&
1030 0 : !::rtl::math::approxEqual( nArg, nComp1 ) && !::rtl::math::approxEqual( nArg, nComp2 );
1031 0 : break;
1032 : case SC_COND_DUPLICATE:
1033 : case SC_COND_NOTDUPLICATE:
1034 0 : if( pCondFormat )
1035 : {
1036 0 : bValid = IsDuplicate( nArg, OUString() );
1037 0 : if( eOp == SC_COND_NOTDUPLICATE )
1038 0 : bValid = !bValid;
1039 : }
1040 0 : break;
1041 : case SC_COND_DIRECT:
1042 0 : bValid = !::rtl::math::approxEqual( nComp1, 0.0 );
1043 0 : break;
1044 : case SC_COND_TOP10:
1045 0 : bValid = IsTopNElement( nArg );
1046 0 : break;
1047 : case SC_COND_BOTTOM10:
1048 0 : bValid = IsBottomNElement( nArg );
1049 0 : break;
1050 : case SC_COND_TOP_PERCENT:
1051 0 : bValid = IsTopNPercent( nArg );
1052 0 : break;
1053 : case SC_COND_BOTTOM_PERCENT:
1054 0 : bValid = IsBottomNPercent( nArg );
1055 0 : break;
1056 : case SC_COND_ABOVE_AVERAGE:
1057 : case SC_COND_ABOVE_EQUAL_AVERAGE:
1058 0 : bValid = IsAboveAverage( nArg, eOp == SC_COND_ABOVE_EQUAL_AVERAGE );
1059 0 : break;
1060 : case SC_COND_BELOW_AVERAGE:
1061 : case SC_COND_BELOW_EQUAL_AVERAGE:
1062 0 : bValid = IsBelowAverage( nArg, eOp == SC_COND_BELOW_EQUAL_AVERAGE );
1063 0 : break;
1064 : case SC_COND_ERROR:
1065 : case SC_COND_NOERROR:
1066 0 : bValid = IsError( rPos );
1067 0 : if( eOp == SC_COND_NOERROR )
1068 0 : bValid = !bValid;
1069 0 : break;
1070 : case SC_COND_BEGINS_WITH:
1071 0 : if(aStrVal1.isEmpty())
1072 : {
1073 0 : OUString aStr = OUString::number(nVal1);
1074 0 : OUString aStr2 = OUString::number(nArg);
1075 0 : bValid = aStr2.startsWith(aStr);
1076 : }
1077 : else
1078 : {
1079 0 : OUString aStr2 = OUString::number(nArg);
1080 0 : bValid = aStr2.startsWith(aStrVal1);
1081 : }
1082 0 : break;
1083 : case SC_COND_ENDS_WITH:
1084 0 : if(aStrVal1.isEmpty())
1085 : {
1086 0 : OUString aStr = OUString::number(nVal1);
1087 0 : OUString aStr2 = OUString::number(nArg);
1088 0 : bValid = !aStr2.endsWith(aStr);
1089 : }
1090 : else
1091 : {
1092 0 : OUString aStr2 = OUString::number(nArg);
1093 0 : bValid = !aStr2.endsWith(aStrVal1);
1094 : }
1095 0 : break;
1096 : case SC_COND_CONTAINS_TEXT:
1097 : case SC_COND_NOT_CONTAINS_TEXT:
1098 0 : if(aStrVal1.isEmpty())
1099 : {
1100 0 : OUString aStr = OUString::number(nVal1);
1101 0 : OUString aStr2 = OUString::number(nArg);
1102 0 : bValid = aStr2.indexOf(aStr) != -1;
1103 : }
1104 : else
1105 : {
1106 0 : OUString aStr2 = OUString::number(nArg);
1107 0 : bValid = aStr2.indexOf(aStrVal1) != -1;
1108 : }
1109 :
1110 0 : if( eOp == SC_COND_NOT_CONTAINS_TEXT )
1111 0 : bValid = !bValid;
1112 0 : break;
1113 : default:
1114 : SAL_WARN("sc", "unknown operation at ScConditionEntry");
1115 0 : break;
1116 : }
1117 0 : return bValid;
1118 : }
1119 :
1120 0 : bool ScConditionEntry::IsValidStr( const OUString& rArg, const ScAddress& rPos ) const
1121 : {
1122 0 : bool bValid = false;
1123 : // Interpret muss schon gerufen sein
1124 :
1125 0 : if ( eOp == SC_COND_DIRECT ) // Formel ist unabhaengig vom Inhalt
1126 0 : return !::rtl::math::approxEqual( nVal1, 0.0 );
1127 :
1128 0 : if ( eOp == SC_COND_DUPLICATE || eOp == SC_COND_NOTDUPLICATE )
1129 : {
1130 0 : if( pCondFormat && !rArg.isEmpty() )
1131 : {
1132 0 : bValid = IsDuplicate( 0.0, rArg );
1133 0 : if( eOp == SC_COND_NOTDUPLICATE )
1134 0 : bValid = !bValid;
1135 0 : return bValid;
1136 : }
1137 : }
1138 :
1139 : // If number contains condition, always false, except for "not equal".
1140 :
1141 0 : if ( !bIsStr1 && (eOp != SC_COND_ERROR && eOp != SC_COND_NOERROR) )
1142 0 : return ( eOp == SC_COND_NOTEQUAL );
1143 0 : if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
1144 0 : if ( !bIsStr2 )
1145 0 : return false;
1146 :
1147 0 : OUString aUpVal1( aStrVal1 ); //! als Member? (dann auch in Interpret setzen)
1148 0 : OUString aUpVal2( aStrVal2 );
1149 :
1150 0 : if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
1151 0 : if (ScGlobal::GetCollator()->compareString( aUpVal1, aUpVal2 ) > 0)
1152 : {
1153 : // richtige Reihenfolge fuer Wertebereich
1154 0 : OUString aTemp( aUpVal1 ); aUpVal1 = aUpVal2; aUpVal2 = aTemp;
1155 : }
1156 :
1157 0 : switch ( eOp )
1158 : {
1159 : case SC_COND_EQUAL:
1160 : bValid = (ScGlobal::GetCollator()->compareString(
1161 0 : rArg, aUpVal1 ) == 0);
1162 0 : break;
1163 : case SC_COND_NOTEQUAL:
1164 : bValid = (ScGlobal::GetCollator()->compareString(
1165 0 : rArg, aUpVal1 ) != 0);
1166 0 : break;
1167 : case SC_COND_TOP_PERCENT:
1168 : case SC_COND_BOTTOM_PERCENT:
1169 : case SC_COND_TOP10:
1170 : case SC_COND_BOTTOM10:
1171 : case SC_COND_ABOVE_AVERAGE:
1172 : case SC_COND_BELOW_AVERAGE:
1173 0 : return false;
1174 : case SC_COND_ERROR:
1175 : case SC_COND_NOERROR:
1176 0 : bValid = IsError( rPos );
1177 0 : if(eOp == SC_COND_NOERROR)
1178 0 : bValid = !bValid;
1179 0 : break;
1180 : case SC_COND_BEGINS_WITH:
1181 0 : bValid = rArg.startsWith(aUpVal1);
1182 0 : break;
1183 : case SC_COND_ENDS_WITH:
1184 0 : bValid = rArg.endsWith(aUpVal1);
1185 0 : break;
1186 : case SC_COND_CONTAINS_TEXT:
1187 : case SC_COND_NOT_CONTAINS_TEXT:
1188 0 : bValid = rArg.indexOf(aUpVal1) != -1;
1189 0 : if(eOp == SC_COND_NOT_CONTAINS_TEXT)
1190 0 : bValid = !bValid;
1191 0 : break;
1192 : default:
1193 : {
1194 : sal_Int32 nCompare = ScGlobal::GetCollator()->compareString(
1195 0 : rArg, aUpVal1 );
1196 0 : switch ( eOp )
1197 : {
1198 : case SC_COND_GREATER:
1199 0 : bValid = ( nCompare > 0 );
1200 0 : break;
1201 : case SC_COND_EQGREATER:
1202 0 : bValid = ( nCompare >= 0 );
1203 0 : break;
1204 : case SC_COND_LESS:
1205 0 : bValid = ( nCompare < 0 );
1206 0 : break;
1207 : case SC_COND_EQLESS:
1208 0 : bValid = ( nCompare <= 0 );
1209 0 : break;
1210 : case SC_COND_BETWEEN:
1211 : case SC_COND_NOTBETWEEN:
1212 : // Test auf NOTBETWEEN:
1213 0 : bValid = ( nCompare < 0 ||
1214 : ScGlobal::GetCollator()->compareString( rArg,
1215 0 : aUpVal2 ) > 0 );
1216 0 : if ( eOp == SC_COND_BETWEEN )
1217 0 : bValid = !bValid;
1218 0 : break;
1219 : // SC_COND_DIRECT schon oben abgefragt
1220 : default:
1221 : SAL_WARN("sc", "unbekannte Operation bei ScConditionEntry");
1222 0 : bValid = false;
1223 0 : break;
1224 : }
1225 : }
1226 : }
1227 0 : return bValid;
1228 : }
1229 :
1230 0 : bool ScConditionEntry::IsCellValid( ScRefCellValue& rCell, const ScAddress& rPos ) const
1231 : {
1232 0 : ((ScConditionEntry*)this)->Interpret(rPos); // Formeln auswerten
1233 :
1234 0 : double nArg = 0.0;
1235 0 : OUString aArgStr;
1236 0 : bool bVal = lcl_GetCellContent( rCell, bIsStr1, nArg, aArgStr, mpDoc );
1237 0 : if (bVal)
1238 0 : return IsValid( nArg, rPos );
1239 : else
1240 0 : return IsValidStr( aArgStr, rPos );
1241 : }
1242 :
1243 0 : OUString ScConditionEntry::GetExpression( const ScAddress& rCursor, sal_uInt16 nIndex,
1244 : sal_uLong nNumFmt,
1245 : const FormulaGrammar::Grammar eGrammar ) const
1246 : {
1247 : assert( nIndex <= 1);
1248 0 : OUString aRet;
1249 :
1250 0 : if ( FormulaGrammar::isEnglish( eGrammar) && nNumFmt == 0 )
1251 0 : nNumFmt = mpDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US );
1252 :
1253 0 : if ( nIndex==0 )
1254 : {
1255 0 : if ( pFormula1 )
1256 : {
1257 0 : ScCompiler aComp(mpDoc, rCursor, *pFormula1);
1258 0 : aComp.SetGrammar(eGrammar);
1259 0 : OUStringBuffer aBuffer;
1260 0 : aComp.CreateStringFromTokenArray( aBuffer );
1261 0 : aRet = aBuffer.makeStringAndClear();
1262 : }
1263 0 : else if (bIsStr1)
1264 : {
1265 0 : aRet = "\"";
1266 0 : aRet += aStrVal1;
1267 0 : aRet += "\"";
1268 : }
1269 : else
1270 0 : mpDoc->GetFormatTable()->GetInputLineString(nVal1, nNumFmt, aRet);
1271 : }
1272 0 : else if ( nIndex==1 )
1273 : {
1274 0 : if ( pFormula2 )
1275 : {
1276 0 : ScCompiler aComp(mpDoc, rCursor, *pFormula2);
1277 0 : aComp.SetGrammar(eGrammar);
1278 0 : OUStringBuffer aBuffer;
1279 0 : aComp.CreateStringFromTokenArray( aBuffer );
1280 0 : aRet = aBuffer.makeStringAndClear();
1281 : }
1282 0 : else if (bIsStr2)
1283 : {
1284 0 : aRet = "\"";
1285 0 : aRet += aStrVal2;
1286 0 : aRet += "\"";
1287 : }
1288 : else
1289 0 : mpDoc->GetFormatTable()->GetInputLineString(nVal2, nNumFmt, aRet);
1290 : }
1291 :
1292 0 : return aRet;
1293 : }
1294 :
1295 0 : ScTokenArray* ScConditionEntry::CreateTokenArry( sal_uInt16 nIndex ) const
1296 : {
1297 : assert(nIndex <= 1);
1298 0 : ScTokenArray* pRet = NULL;
1299 0 : ScAddress aAddr;
1300 :
1301 0 : if ( nIndex==0 )
1302 : {
1303 0 : if ( pFormula1 )
1304 0 : pRet = new ScTokenArray( *pFormula1 );
1305 : else
1306 : {
1307 0 : pRet = new ScTokenArray();
1308 0 : if (bIsStr1)
1309 0 : pRet->AddString( aStrVal1 );
1310 : else
1311 0 : pRet->AddDouble( nVal1 );
1312 : }
1313 : }
1314 0 : else if ( nIndex==1 )
1315 : {
1316 0 : if ( pFormula2 )
1317 0 : pRet = new ScTokenArray( *pFormula2 );
1318 : else
1319 : {
1320 0 : pRet = new ScTokenArray();
1321 0 : if (bIsStr2)
1322 0 : pRet->AddString( aStrVal2 );
1323 : else
1324 0 : pRet->AddDouble( nVal2 );
1325 : }
1326 : }
1327 :
1328 0 : return pRet;
1329 : }
1330 :
1331 0 : void ScConditionEntry::SourceChanged( const ScAddress& rChanged )
1332 : {
1333 0 : for (sal_uInt16 nPass = 0; nPass < 2; nPass++)
1334 : {
1335 0 : ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
1336 0 : if (pFormula)
1337 : {
1338 0 : pFormula->Reset();
1339 : ScToken* t;
1340 0 : while ( ( t = static_cast<ScToken*>(pFormula->GetNextReference()) ) != NULL )
1341 : {
1342 0 : SingleDoubleRefProvider aProv( *t );
1343 0 : if ( aProv.Ref1.IsColRel() || aProv.Ref1.IsRowRel() || aProv.Ref1.IsTabRel() ||
1344 0 : aProv.Ref2.IsColRel() || aProv.Ref2.IsRowRel() || aProv.Ref2.IsTabRel() )
1345 : {
1346 : // absolut muss getroffen sein, relativ bestimmt Bereich
1347 :
1348 0 : bool bHit = true;
1349 : SCsCOL nCol1;
1350 : SCsROW nRow1;
1351 : SCsTAB nTab1;
1352 : SCsCOL nCol2;
1353 : SCsROW nRow2;
1354 : SCsTAB nTab2;
1355 :
1356 0 : if ( aProv.Ref1.IsColRel() )
1357 0 : nCol2 = rChanged.Col() - aProv.Ref1.Col();
1358 : else
1359 : {
1360 0 : bHit &= (rChanged.Col() >= aProv.Ref1.Col());
1361 0 : nCol2 = MAXCOL;
1362 : }
1363 0 : if ( aProv.Ref1.IsRowRel() )
1364 0 : nRow2 = rChanged.Row() - aProv.Ref1.Row();
1365 : else
1366 : {
1367 0 : bHit &= ( rChanged.Row() >= aProv.Ref1.Row() );
1368 0 : nRow2 = MAXROW;
1369 : }
1370 0 : if ( aProv.Ref1.IsTabRel() )
1371 0 : nTab2 = rChanged.Tab() - aProv.Ref1.Tab();
1372 : else
1373 : {
1374 0 : bHit &= (rChanged.Tab() >= aProv.Ref1.Tab());
1375 0 : nTab2 = MAXTAB;
1376 : }
1377 :
1378 0 : if ( aProv.Ref2.IsColRel() )
1379 0 : nCol1 = rChanged.Col() - aProv.Ref2.Col();
1380 : else
1381 : {
1382 0 : bHit &= ( rChanged.Col() <= aProv.Ref2.Col() );
1383 0 : nCol1 = 0;
1384 : }
1385 0 : if ( aProv.Ref2.IsRowRel() )
1386 0 : nRow1 = rChanged.Row() - aProv.Ref2.Row();
1387 : else
1388 : {
1389 0 : bHit &= (rChanged.Row() <= aProv.Ref2.Row());
1390 0 : nRow1 = 0;
1391 : }
1392 0 : if ( aProv.Ref2.IsTabRel() )
1393 0 : nTab1 = rChanged.Tab() - aProv.Ref2.Tab();
1394 : else
1395 : {
1396 0 : bHit &= (rChanged.Tab() <= aProv.Ref2.Tab());
1397 0 : nTab1 = 0;
1398 : }
1399 :
1400 0 : if ( bHit )
1401 : {
1402 : //! begrenzen
1403 :
1404 0 : ScRange aPaint( nCol1,nRow1,nTab1, nCol2,nRow2,nTab2 );
1405 :
1406 : // kein Paint, wenn es nur die Zelle selber ist
1407 0 : if ( aPaint.IsValid() && (aPaint.aStart != rChanged || aPaint.aEnd != rChanged ))
1408 0 : DataChanged( &aPaint );
1409 : }
1410 : }
1411 0 : }
1412 : }
1413 : }
1414 0 : }
1415 :
1416 0 : ScAddress ScConditionEntry::GetValidSrcPos() const
1417 : {
1418 : // return a position that's adjusted to allow textual representation of expressions if possible
1419 :
1420 0 : SCTAB nMinTab = aSrcPos.Tab();
1421 0 : SCTAB nMaxTab = nMinTab;
1422 :
1423 0 : for (sal_uInt16 nPass = 0; nPass < 2; nPass++)
1424 : {
1425 0 : ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
1426 0 : if (pFormula)
1427 : {
1428 0 : pFormula->Reset();
1429 : ScToken* t;
1430 0 : while ( ( t = static_cast<ScToken*>(pFormula->GetNextReference()) ) != NULL )
1431 : {
1432 0 : ScSingleRefData& rRef1 = t->GetSingleRef();
1433 0 : ScAddress aAbs = rRef1.toAbs(aSrcPos);
1434 0 : if (!rRef1.IsTabDeleted())
1435 : {
1436 0 : if (aAbs.Tab() < nMinTab)
1437 0 : nMinTab = aAbs.Tab();
1438 0 : if (aAbs.Tab() > nMaxTab)
1439 0 : nMaxTab = aAbs.Tab();
1440 : }
1441 0 : if ( t->GetType() == svDoubleRef )
1442 : {
1443 0 : ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
1444 0 : aAbs = rRef2.toAbs(aSrcPos);
1445 0 : if (!rRef2.IsTabDeleted())
1446 : {
1447 0 : if (aAbs.Tab() < nMinTab)
1448 0 : nMinTab = aAbs.Tab();
1449 0 : if (aAbs.Tab() > nMaxTab)
1450 0 : nMaxTab = aAbs.Tab();
1451 : }
1452 : }
1453 : }
1454 : }
1455 : }
1456 :
1457 0 : ScAddress aValidPos = aSrcPos;
1458 0 : SCTAB nTabCount = mpDoc->GetTableCount();
1459 0 : if ( nMaxTab >= nTabCount && nMinTab > 0 )
1460 0 : aValidPos.SetTab( aSrcPos.Tab() - nMinTab ); // so the lowest tab ref will be on 0
1461 :
1462 0 : if ( aValidPos.Tab() >= nTabCount )
1463 0 : aValidPos.SetTab( nTabCount - 1 ); // ensure a valid position even if some references will be invalid
1464 :
1465 0 : return aValidPos;
1466 : }
1467 :
1468 0 : void ScConditionEntry::DataChanged( const ScRange* /* pModified */ ) const
1469 : {
1470 : // nix
1471 0 : }
1472 :
1473 0 : bool ScConditionEntry::MarkUsedExternalReferences() const
1474 : {
1475 0 : bool bAllMarked = false;
1476 0 : for (sal_uInt16 nPass = 0; !bAllMarked && nPass < 2; nPass++)
1477 : {
1478 0 : ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
1479 0 : if (pFormula)
1480 0 : bAllMarked = mpDoc->MarkUsedExternalReferences(*pFormula, aSrcPos);
1481 : }
1482 0 : return bAllMarked;
1483 : }
1484 :
1485 0 : ScFormatEntry* ScConditionEntry::Clone(ScDocument* pDoc) const
1486 : {
1487 0 : return new ScConditionEntry(pDoc, *this);
1488 : }
1489 :
1490 0 : ScConditionMode ScConditionEntry::GetModeFromApi(sal_Int32 nOperation)
1491 : {
1492 0 : ScConditionMode eMode = SC_COND_NONE;
1493 0 : switch (nOperation)
1494 : {
1495 : case com::sun::star::sheet::ConditionOperator2::EQUAL:
1496 0 : eMode = SC_COND_EQUAL;
1497 0 : break;
1498 : case com::sun::star::sheet::ConditionOperator2::LESS:
1499 0 : eMode = SC_COND_LESS;
1500 0 : break;
1501 : case com::sun::star::sheet::ConditionOperator2::GREATER:
1502 0 : eMode = SC_COND_GREATER;
1503 0 : break;
1504 : case com::sun::star::sheet::ConditionOperator2::LESS_EQUAL:
1505 0 : eMode = SC_COND_EQLESS;
1506 0 : break;
1507 : case com::sun::star::sheet::ConditionOperator2::GREATER_EQUAL:
1508 0 : eMode = SC_COND_EQGREATER;
1509 0 : break;
1510 : case com::sun::star::sheet::ConditionOperator2::NOT_EQUAL:
1511 0 : eMode = SC_COND_NOTEQUAL;
1512 0 : break;
1513 : case com::sun::star::sheet::ConditionOperator2::BETWEEN:
1514 0 : eMode = SC_COND_BETWEEN;
1515 0 : break;
1516 : case com::sun::star::sheet::ConditionOperator2::NOT_BETWEEN:
1517 0 : eMode = SC_COND_NOTBETWEEN;
1518 0 : break;
1519 : case com::sun::star::sheet::ConditionOperator2::FORMULA:
1520 0 : eMode = SC_COND_DIRECT;
1521 0 : break;
1522 : case com::sun::star::sheet::ConditionOperator2::DUPLICATE:
1523 0 : eMode = SC_COND_DUPLICATE;
1524 0 : break;
1525 : case com::sun::star::sheet::ConditionOperator2::NOT_DUPLICATE:
1526 0 : eMode = SC_COND_NOTDUPLICATE;
1527 0 : break;
1528 : default:
1529 0 : break;
1530 : }
1531 0 : return eMode;
1532 : }
1533 :
1534 0 : void ScConditionEntry::startRendering()
1535 : {
1536 0 : mpCache.reset();
1537 0 : }
1538 :
1539 0 : void ScConditionEntry::endRendering()
1540 : {
1541 0 : mpCache.reset();
1542 0 : }
1543 :
1544 0 : ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
1545 : const OUString& rExpr1, const OUString& rExpr2,
1546 : ScDocument* pDocument, const ScAddress& rPos,
1547 : const OUString& rStyle,
1548 : const OUString& rExprNmsp1, const OUString& rExprNmsp2,
1549 : FormulaGrammar::Grammar eGrammar1,
1550 : FormulaGrammar::Grammar eGrammar2 ) :
1551 : ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2 ),
1552 0 : aStyleName( rStyle )
1553 : {
1554 0 : }
1555 :
1556 0 : ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
1557 : const ScTokenArray* pArr1, const ScTokenArray* pArr2,
1558 : ScDocument* pDocument, const ScAddress& rPos,
1559 : const OUString& rStyle ) :
1560 : ScConditionEntry( eOper, pArr1, pArr2, pDocument, rPos ),
1561 0 : aStyleName( rStyle )
1562 : {
1563 0 : }
1564 :
1565 0 : ScCondFormatEntry::ScCondFormatEntry( const ScCondFormatEntry& r ) :
1566 : ScConditionEntry( r ),
1567 0 : aStyleName( r.aStyleName )
1568 : {
1569 0 : }
1570 :
1571 0 : ScCondFormatEntry::ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r ) :
1572 : ScConditionEntry( pDocument, r ),
1573 0 : aStyleName( r.aStyleName )
1574 : {
1575 0 : }
1576 :
1577 0 : bool ScCondFormatEntry::operator== ( const ScCondFormatEntry& r ) const
1578 : {
1579 0 : return ScConditionEntry::operator==( r ) &&
1580 0 : aStyleName == r.aStyleName;
1581 : }
1582 :
1583 0 : ScCondFormatEntry::~ScCondFormatEntry()
1584 : {
1585 0 : }
1586 :
1587 0 : void ScCondFormatEntry::DataChanged( const ScRange* pModified ) const
1588 : {
1589 0 : if ( pCondFormat )
1590 0 : pCondFormat->DoRepaint( pModified );
1591 0 : }
1592 :
1593 0 : ScFormatEntry* ScCondFormatEntry::Clone( ScDocument* pDoc ) const
1594 : {
1595 0 : return new ScCondFormatEntry( pDoc, *this );
1596 : }
1597 :
1598 0 : ScCondDateFormatEntry::ScCondDateFormatEntry( ScDocument* pDoc )
1599 : : ScFormatEntry( pDoc )
1600 0 : , meType(condformat::TODAY)
1601 : {
1602 0 : }
1603 :
1604 0 : ScCondDateFormatEntry::ScCondDateFormatEntry( ScDocument* pDoc, const ScCondDateFormatEntry& rFormat ):
1605 : ScFormatEntry( pDoc ),
1606 : meType( rFormat.meType ),
1607 0 : maStyleName( rFormat.maStyleName )
1608 : {
1609 0 : }
1610 :
1611 0 : bool ScCondDateFormatEntry::IsValid( const ScAddress& rPos ) const
1612 : {
1613 0 : CellType eCellType = mpDoc->GetCellType(rPos);
1614 :
1615 0 : if (eCellType == CELLTYPE_NONE)
1616 : // empty cell.
1617 0 : return false;
1618 :
1619 0 : if (eCellType != CELLTYPE_VALUE && eCellType != CELLTYPE_FORMULA)
1620 : // non-numerical cell.
1621 0 : return false;
1622 :
1623 0 : if( !mpCache )
1624 0 : mpCache.reset( new Date( Date::SYSTEM ) );
1625 :
1626 0 : const Date& rActDate = *mpCache;
1627 0 : SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
1628 0 : long nCurrentDate = rActDate - *(pFormatter->GetNullDate());
1629 :
1630 0 : double nVal = mpDoc->GetValue(rPos);
1631 0 : long nCellDate = (long) ::rtl::math::approxFloor(nVal);
1632 0 : Date aCellDate = *(pFormatter->GetNullDate());
1633 0 : aCellDate += (long) ::rtl::math::approxFloor(nVal);
1634 :
1635 0 : switch(meType)
1636 : {
1637 : case condformat::TODAY:
1638 0 : if( nCurrentDate == nCellDate )
1639 0 : return true;
1640 0 : break;
1641 : case condformat::TOMORROW:
1642 0 : if( nCurrentDate == nCellDate -1 )
1643 0 : return true;
1644 0 : break;
1645 : case condformat::YESTERDAY:
1646 0 : if( nCurrentDate == nCellDate + 1)
1647 0 : return true;
1648 0 : break;
1649 : case condformat::LAST7DAYS:
1650 0 : if( nCurrentDate >= nCellDate && nCurrentDate - 7 < nCellDate )
1651 0 : return true;
1652 0 : break;
1653 : case condformat::LASTWEEK:
1654 0 : if( rActDate.GetDayOfWeek() != SUNDAY )
1655 : {
1656 0 : Date aBegin(rActDate - 8 - static_cast<long>(rActDate.GetDayOfWeek()));
1657 0 : Date aEnd(rActDate - 2 -static_cast<long>(rActDate.GetDayOfWeek()));
1658 0 : return aCellDate.IsBetween( aBegin, aEnd );
1659 : }
1660 : else
1661 : {
1662 0 : Date aBegin(rActDate - 8);
1663 0 : Date aEnd(rActDate - 1);
1664 0 : return aCellDate.IsBetween( aBegin, aEnd );
1665 : }
1666 : break;
1667 : case condformat::THISWEEK:
1668 0 : if( rActDate.GetDayOfWeek() != SUNDAY )
1669 : {
1670 0 : Date aBegin(rActDate - 1 - static_cast<long>(rActDate.GetDayOfWeek()));
1671 0 : Date aEnd(rActDate + 5 - static_cast<long>(rActDate.GetDayOfWeek()));
1672 0 : return aCellDate.IsBetween( aBegin, aEnd );
1673 : }
1674 : else
1675 : {
1676 0 : Date aEnd( rActDate + 6);
1677 0 : return aCellDate.IsBetween( rActDate, aEnd );
1678 : }
1679 : break;
1680 : case condformat::NEXTWEEK:
1681 0 : if( rActDate.GetDayOfWeek() != SUNDAY )
1682 : {
1683 0 : return aCellDate.IsBetween( rActDate + 6 - static_cast<long>(rActDate.GetDayOfWeek()), rActDate + 12 - static_cast<long>(rActDate.GetDayOfWeek()) );
1684 : }
1685 : else
1686 : {
1687 0 : return aCellDate.IsBetween( rActDate + 7, rActDate + 13 );
1688 : }
1689 : break;
1690 : case condformat::LASTMONTH:
1691 0 : if( rActDate.GetMonth() == 1 )
1692 : {
1693 0 : if( aCellDate.GetMonth() == 12 && rActDate.GetYear() == aCellDate.GetYear() + 1 )
1694 0 : return true;
1695 : }
1696 0 : else if( rActDate.GetYear() == aCellDate.GetYear() )
1697 : {
1698 0 : if( rActDate.GetMonth() == aCellDate.GetMonth() + 1)
1699 0 : return true;
1700 : }
1701 0 : break;
1702 : case condformat::THISMONTH:
1703 0 : if( rActDate.GetYear() == aCellDate.GetYear() )
1704 : {
1705 0 : if( rActDate.GetMonth() == aCellDate.GetMonth() )
1706 0 : return true;
1707 : }
1708 0 : break;
1709 : case condformat::NEXTMONTH:
1710 0 : if( rActDate.GetMonth() == 12 )
1711 : {
1712 0 : if( aCellDate.GetMonth() == 1 && rActDate.GetYear() == aCellDate.GetYear() - 1 )
1713 0 : return true;
1714 : }
1715 0 : else if( rActDate.GetYear() == aCellDate.GetYear() )
1716 : {
1717 0 : if( rActDate.GetMonth() == aCellDate.GetMonth() - 1)
1718 0 : return true;
1719 : }
1720 0 : break;
1721 : case condformat::LASTYEAR:
1722 0 : if( rActDate.GetYear() == aCellDate.GetYear() + 1 )
1723 0 : return true;
1724 0 : break;
1725 : case condformat::THISYEAR:
1726 0 : if( rActDate.GetYear() == aCellDate.GetYear() )
1727 0 : return true;
1728 0 : break;
1729 : case condformat::NEXTYEAR:
1730 0 : if( rActDate.GetYear() == aCellDate.GetYear() - 1 )
1731 0 : return true;
1732 0 : break;
1733 : }
1734 :
1735 0 : return false;
1736 : }
1737 :
1738 0 : void ScCondDateFormatEntry::SetDateType( condformat::ScCondFormatDateType eType )
1739 : {
1740 0 : meType = eType;
1741 0 : }
1742 :
1743 0 : condformat::ScCondFormatDateType ScCondDateFormatEntry::GetDateType() const
1744 : {
1745 0 : return meType;
1746 : }
1747 :
1748 0 : const OUString& ScCondDateFormatEntry::GetStyleName() const
1749 : {
1750 0 : return maStyleName;
1751 : }
1752 :
1753 0 : void ScCondDateFormatEntry::SetStyleName( const OUString& rStyleName )
1754 : {
1755 0 : maStyleName = rStyleName;
1756 0 : }
1757 :
1758 0 : ScFormatEntry* ScCondDateFormatEntry::Clone( ScDocument* pDoc ) const
1759 : {
1760 0 : return new ScCondDateFormatEntry( pDoc, *this );
1761 : }
1762 :
1763 0 : bool ScCondDateFormatEntry::operator==( const ScFormatEntry& r ) const
1764 : {
1765 0 : if(r.GetType() != condformat::DATE)
1766 0 : return false;
1767 :
1768 0 : const ScCondDateFormatEntry& rEntry = static_cast<const ScCondDateFormatEntry&>(r);
1769 :
1770 0 : if(rEntry.meType != meType)
1771 0 : return false;
1772 :
1773 0 : return rEntry.maStyleName == maStyleName;
1774 : }
1775 :
1776 0 : void ScCondDateFormatEntry::startRendering()
1777 : {
1778 0 : mpCache.reset();
1779 0 : }
1780 :
1781 0 : void ScCondDateFormatEntry::endRendering()
1782 : {
1783 0 : mpCache.reset();
1784 0 : }
1785 :
1786 0 : ScConditionalFormat::ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* pDocument) :
1787 : pDoc( pDocument ),
1788 0 : nKey( nNewKey )
1789 : {
1790 0 : }
1791 :
1792 0 : ScConditionalFormat* ScConditionalFormat::Clone(ScDocument* pNewDoc) const
1793 : {
1794 : // echte Kopie der Formeln (fuer Ref-Undo / zwischen Dokumenten)
1795 :
1796 0 : if (!pNewDoc)
1797 0 : pNewDoc = pDoc;
1798 :
1799 0 : ScConditionalFormat* pNew = new ScConditionalFormat(nKey, pNewDoc);
1800 :
1801 0 : for (CondFormatContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
1802 : {
1803 0 : ScFormatEntry* pNewEntry = itr->Clone(pNewDoc);
1804 0 : pNew->maEntries.push_back( pNewEntry );
1805 0 : pNewEntry->SetParent(pNew);
1806 : }
1807 0 : pNew->AddRange( maRanges );
1808 :
1809 0 : return pNew;
1810 : }
1811 :
1812 0 : bool ScConditionalFormat::EqualEntries( const ScConditionalFormat& r ) const
1813 : {
1814 0 : if( size() != r.size())
1815 0 : return false;
1816 :
1817 : //! auf gleiche Eintraege in anderer Reihenfolge testen ???
1818 :
1819 0 : for (sal_uInt16 i=0; i<size(); i++)
1820 0 : if ( ! (maEntries == r.maEntries ) )
1821 0 : return false;
1822 :
1823 : // right now don't check for same range
1824 : // we only use this method to merge same conditional formats from
1825 : // old ODF data structure
1826 0 : return true;
1827 : }
1828 :
1829 0 : void ScConditionalFormat::AddRange( const ScRangeList& rRanges )
1830 : {
1831 0 : maRanges = rRanges;
1832 0 : }
1833 :
1834 0 : void ScConditionalFormat::AddEntry( ScFormatEntry* pNew )
1835 : {
1836 0 : maEntries.push_back(pNew);
1837 0 : pNew->SetParent(this);
1838 0 : }
1839 :
1840 0 : bool ScConditionalFormat::IsEmpty() const
1841 : {
1842 0 : return maEntries.empty();
1843 : }
1844 :
1845 0 : size_t ScConditionalFormat::size() const
1846 : {
1847 0 : return maEntries.size();
1848 : }
1849 :
1850 0 : ScConditionalFormat::~ScConditionalFormat()
1851 : {
1852 0 : }
1853 :
1854 0 : const ScFormatEntry* ScConditionalFormat::GetEntry( sal_uInt16 nPos ) const
1855 : {
1856 0 : if ( nPos < size() )
1857 0 : return &maEntries[nPos];
1858 : else
1859 0 : return NULL;
1860 : }
1861 :
1862 0 : const OUString& ScConditionalFormat::GetCellStyle( ScRefCellValue& rCell, const ScAddress& rPos ) const
1863 : {
1864 0 : for (CondFormatContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
1865 : {
1866 0 : if(itr->GetType() == condformat::CONDITION)
1867 : {
1868 0 : const ScCondFormatEntry& rEntry = static_cast<const ScCondFormatEntry&>(*itr);
1869 0 : if (rEntry.IsCellValid(rCell, rPos))
1870 0 : return rEntry.GetStyle();
1871 : }
1872 0 : else if(itr->GetType() == condformat::DATE)
1873 : {
1874 0 : const ScCondDateFormatEntry& rEntry = static_cast<const ScCondDateFormatEntry&>(*itr);
1875 0 : if (rEntry.IsValid( rPos ))
1876 0 : return rEntry.GetStyleName();
1877 : }
1878 : }
1879 :
1880 0 : return EMPTY_OUSTRING;
1881 : }
1882 :
1883 0 : ScCondFormatData ScConditionalFormat::GetData( ScRefCellValue& rCell, const ScAddress& rPos ) const
1884 : {
1885 0 : ScCondFormatData aData;
1886 0 : for(CondFormatContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
1887 : {
1888 0 : if(itr->GetType() == condformat::CONDITION && aData.aStyleName.isEmpty())
1889 : {
1890 0 : const ScCondFormatEntry& rEntry = static_cast<const ScCondFormatEntry&>(*itr);
1891 0 : if (rEntry.IsCellValid(rCell, rPos))
1892 0 : aData.aStyleName = rEntry.GetStyle();
1893 : }
1894 0 : else if(itr->GetType() == condformat::COLORSCALE && !aData.pColorScale)
1895 : {
1896 0 : const ScColorScaleFormat& rEntry = static_cast<const ScColorScaleFormat&>(*itr);
1897 0 : aData.pColorScale = rEntry.GetColor(rPos);
1898 : }
1899 0 : else if(itr->GetType() == condformat::DATABAR && !aData.pDataBar)
1900 : {
1901 0 : const ScDataBarFormat& rEntry = static_cast<const ScDataBarFormat&>(*itr);
1902 0 : aData.pDataBar = rEntry.GetDataBarInfo(rPos);
1903 : }
1904 0 : else if(itr->GetType() == condformat::ICONSET && !aData.pIconSet)
1905 : {
1906 0 : const ScIconSetFormat& rEntry = static_cast<const ScIconSetFormat&>(*itr);
1907 0 : aData.pIconSet = rEntry.GetIconSetInfo(rPos);
1908 : }
1909 0 : else if(itr->GetType() == condformat::DATE && aData.aStyleName.isEmpty())
1910 : {
1911 0 : const ScCondDateFormatEntry& rEntry = static_cast<const ScCondDateFormatEntry&>(*itr);
1912 0 : if ( rEntry.IsValid( rPos ) )
1913 0 : aData.aStyleName = rEntry.GetStyleName();
1914 : }
1915 : }
1916 0 : return aData;
1917 : }
1918 :
1919 0 : void ScConditionalFormat::DoRepaint( const ScRange* pModified )
1920 : {
1921 0 : if(pModified)
1922 : {
1923 0 : if(maRanges.Intersects(*pModified))
1924 0 : pDoc->RepaintRange(*pModified);
1925 : }
1926 : else
1927 : {
1928 : // all conditional format cells
1929 0 : pDoc->RepaintRange( maRanges );
1930 : }
1931 0 : }
1932 :
1933 0 : void ScConditionalFormat::CompileAll()
1934 : {
1935 0 : for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
1936 0 : if(itr->GetType() == condformat::CONDITION)
1937 0 : static_cast<ScCondFormatEntry&>(*itr).CompileAll();
1938 0 : }
1939 :
1940 0 : void ScConditionalFormat::CompileXML()
1941 : {
1942 0 : for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
1943 0 : if(itr->GetType() == condformat::CONDITION)
1944 0 : static_cast<ScCondFormatEntry&>(*itr).CompileXML();
1945 0 : }
1946 :
1947 0 : void ScConditionalFormat::UpdateReference( sc::RefUpdateContext& rCxt, bool bCopyAsMove )
1948 : {
1949 0 : for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
1950 0 : itr->UpdateReference(rCxt);
1951 :
1952 0 : if (rCxt.meMode == URM_COPY && bCopyAsMove)
1953 0 : maRanges.UpdateReference(URM_MOVE, pDoc, rCxt.maRange, rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
1954 : else
1955 0 : maRanges.UpdateReference(rCxt.meMode, pDoc, rCxt.maRange, rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
1956 0 : }
1957 :
1958 0 : void ScConditionalFormat::InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowPos, SCSIZE nSize)
1959 : {
1960 0 : maRanges.InsertRow(nTab, nColStart, nColEnd, nRowPos, nSize);
1961 0 : }
1962 :
1963 0 : void ScConditionalFormat::InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColPos, SCSIZE nSize)
1964 : {
1965 0 : maRanges.InsertCol(nTab, nRowStart, nRowEnd, nColPos, nSize);
1966 0 : }
1967 :
1968 0 : void ScConditionalFormat::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt )
1969 : {
1970 0 : for (CondFormatContainer::iterator it = maEntries.begin(); it != maEntries.end(); ++it)
1971 0 : it->UpdateInsertTab(rCxt);
1972 0 : }
1973 :
1974 0 : void ScConditionalFormat::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt )
1975 : {
1976 0 : for (CondFormatContainer::iterator it = maEntries.begin(); it != maEntries.end(); ++it)
1977 0 : it->UpdateDeleteTab(rCxt);
1978 0 : }
1979 :
1980 0 : void ScConditionalFormat::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt )
1981 : {
1982 0 : size_t n = maRanges.size();
1983 0 : SCTAB nMinTab = std::min<SCTAB>(rCxt.mnOldPos, rCxt.mnNewPos);
1984 0 : SCTAB nMaxTab = std::max<SCTAB>(rCxt.mnOldPos, rCxt.mnNewPos);
1985 0 : for(size_t i = 0; i < n; ++i)
1986 : {
1987 0 : ScRange* pRange = maRanges[i];
1988 0 : SCTAB nTab = pRange->aStart.Tab();
1989 0 : if(nTab < nMinTab || nTab > nMaxTab)
1990 : {
1991 0 : continue;
1992 : }
1993 :
1994 0 : if (nTab == rCxt.mnOldPos)
1995 : {
1996 0 : pRange->aStart.SetTab(rCxt.mnNewPos);
1997 0 : pRange->aEnd.SetTab(rCxt.mnNewPos);
1998 0 : continue;
1999 : }
2000 :
2001 0 : if (rCxt.mnNewPos < rCxt.mnOldPos)
2002 : {
2003 0 : pRange->aStart.IncTab();
2004 0 : pRange->aEnd.IncTab();
2005 : }
2006 : else
2007 : {
2008 0 : pRange->aStart.IncTab(-1);
2009 0 : pRange->aEnd.IncTab(-1);
2010 : }
2011 : }
2012 :
2013 0 : for (CondFormatContainer::iterator it = maEntries.begin(); it != maEntries.end(); ++it)
2014 0 : it->UpdateMoveTab(rCxt);
2015 0 : }
2016 :
2017 0 : void ScConditionalFormat::DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
2018 : {
2019 0 : SCTAB nTab = maRanges[0]->aStart.Tab();
2020 0 : maRanges.DeleteArea( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
2021 0 : }
2022 :
2023 0 : void ScConditionalFormat::RenameCellStyle(const OUString& rOld, const OUString& rNew)
2024 : {
2025 0 : for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
2026 0 : if(itr->GetType() == condformat::CONDITION)
2027 : {
2028 0 : ScCondFormatEntry& rFormat = static_cast<ScCondFormatEntry&>(*itr);
2029 0 : if(rFormat.GetStyle() == rOld)
2030 0 : rFormat.UpdateStyleName( rNew );
2031 : }
2032 0 : }
2033 :
2034 0 : void ScConditionalFormat::SourceChanged( const ScAddress& rAddr )
2035 : {
2036 0 : for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
2037 : {
2038 0 : condformat::ScFormatEntryType eEntryType = itr->GetType();
2039 0 : if( eEntryType == condformat::CONDITION)
2040 : {
2041 0 : ScCondFormatEntry& rFormat = static_cast<ScCondFormatEntry&>(*itr);
2042 0 : rFormat.SourceChanged( rAddr );
2043 : }
2044 0 : else if( eEntryType == condformat::COLORSCALE ||
2045 0 : eEntryType == condformat::DATABAR ||
2046 : eEntryType == condformat::ICONSET )
2047 : {
2048 0 : ScColorFormat& rFormat = static_cast<ScColorFormat&>(*itr);
2049 0 : if(rFormat.NeedsRepaint())
2050 : {
2051 : // we need to repaint the whole range anyway
2052 0 : DoRepaint(NULL);
2053 0 : return;
2054 : }
2055 : }
2056 : }
2057 : }
2058 :
2059 0 : bool ScConditionalFormat::MarkUsedExternalReferences() const
2060 : {
2061 0 : bool bAllMarked = false;
2062 0 : for(CondFormatContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end() && !bAllMarked; ++itr)
2063 0 : if(itr->GetType() == condformat::CONDITION)
2064 : {
2065 0 : const ScCondFormatEntry& rFormat = static_cast<const ScCondFormatEntry&>(*itr);
2066 0 : bAllMarked = rFormat.MarkUsedExternalReferences();
2067 : }
2068 :
2069 0 : return bAllMarked;
2070 : }
2071 :
2072 0 : void ScConditionalFormat::startRendering()
2073 : {
2074 0 : for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
2075 : {
2076 0 : itr->startRendering();
2077 : }
2078 0 : }
2079 :
2080 0 : void ScConditionalFormat::endRendering()
2081 : {
2082 0 : for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
2083 : {
2084 0 : itr->endRendering();
2085 : }
2086 0 : }
2087 :
2088 0 : ScConditionalFormatList::ScConditionalFormatList(const ScConditionalFormatList& rList)
2089 : {
2090 0 : for(const_iterator itr = rList.begin(); itr != rList.end(); ++itr)
2091 0 : InsertNew( itr->Clone() );
2092 0 : }
2093 :
2094 0 : ScConditionalFormatList::ScConditionalFormatList(ScDocument* pDoc, const ScConditionalFormatList& rList)
2095 : {
2096 0 : for(const_iterator itr = rList.begin(); itr != rList.end(); ++itr)
2097 0 : InsertNew( itr->Clone(pDoc) );
2098 0 : }
2099 :
2100 0 : void ScConditionalFormatList::InsertNew( ScConditionalFormat* pNew )
2101 : {
2102 0 : maConditionalFormats.insert(pNew);
2103 0 : }
2104 :
2105 0 : bool ScConditionalFormatList::operator==( const ScConditionalFormatList& r ) const
2106 : {
2107 : // fuer Ref-Undo - interne Variablen werden nicht verglichen
2108 :
2109 0 : sal_uInt16 nCount = size();
2110 0 : bool bEqual = ( nCount == r.size() );
2111 0 : const_iterator locIterator = begin();
2112 0 : for(const_iterator itr = r.begin(); itr != r.end() && bEqual; ++itr, ++locIterator)
2113 0 : if ( !locIterator->EqualEntries(*itr) ) // Eintraege unterschiedlich ?
2114 0 : bEqual = false;
2115 :
2116 0 : return bEqual;
2117 : }
2118 :
2119 0 : ScConditionalFormat* ScConditionalFormatList::GetFormat( sal_uInt32 nKey )
2120 : {
2121 : //! binaer suchen
2122 :
2123 0 : for( iterator itr = begin(); itr != end(); ++itr)
2124 0 : if (itr->GetKey() == nKey)
2125 0 : return &(*itr);
2126 :
2127 : SAL_WARN("sc", "ScConditionalFormatList: Entry not found");
2128 0 : return NULL;
2129 : }
2130 :
2131 0 : const ScConditionalFormat* ScConditionalFormatList::GetFormat( sal_uInt32 nKey ) const
2132 : {
2133 : //! binaer suchen
2134 :
2135 0 : for ( const_iterator itr = begin(); itr != end(); ++itr)
2136 0 : if (itr->GetKey() == nKey)
2137 0 : return &(*itr);
2138 :
2139 : SAL_WARN("sc", "ScConditionalFormatList: Entry not found");
2140 0 : return NULL;
2141 : }
2142 :
2143 0 : void ScConditionalFormatList::CompileAll()
2144 : {
2145 0 : for( iterator itr = begin(); itr != end(); ++itr)
2146 0 : itr->CompileAll();
2147 0 : }
2148 :
2149 0 : void ScConditionalFormatList::CompileXML()
2150 : {
2151 0 : for( iterator itr = begin(); itr != end(); ++itr)
2152 0 : itr->CompileXML();
2153 0 : }
2154 :
2155 0 : void ScConditionalFormatList::UpdateReference( sc::RefUpdateContext& rCxt )
2156 : {
2157 0 : for( iterator itr = begin(); itr != end(); ++itr)
2158 0 : itr->UpdateReference(rCxt);
2159 :
2160 0 : if (rCxt.meMode == URM_INSDEL)
2161 : {
2162 : // need to check which must be deleted
2163 0 : iterator itr = begin();
2164 0 : while(itr != end())
2165 : {
2166 0 : if(itr->GetRange().empty())
2167 0 : maConditionalFormats.erase(itr++);
2168 : else
2169 0 : ++itr;
2170 : }
2171 : }
2172 0 : }
2173 :
2174 0 : void ScConditionalFormatList::InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowPos, SCSIZE nSize)
2175 : {
2176 0 : for(iterator it = begin(), itEnd = end(); it != itEnd; ++it)
2177 0 : it->InsertRow(nTab, nColStart, nColEnd, nRowPos, nSize);
2178 0 : }
2179 :
2180 0 : void ScConditionalFormatList::InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColPos, SCSIZE nSize)
2181 : {
2182 0 : for(iterator it = begin(), itEnd = end(); it != itEnd; ++it)
2183 0 : it->InsertCol(nTab, nRowStart, nRowEnd, nColPos, nSize);
2184 0 : }
2185 :
2186 0 : void ScConditionalFormatList::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt )
2187 : {
2188 0 : for (iterator it = begin(); it != end(); ++it)
2189 0 : it->UpdateInsertTab(rCxt);
2190 0 : }
2191 :
2192 0 : void ScConditionalFormatList::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt )
2193 : {
2194 0 : for (iterator it = begin(); it != end(); ++it)
2195 0 : it->UpdateDeleteTab(rCxt);
2196 0 : }
2197 :
2198 0 : void ScConditionalFormatList::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt )
2199 : {
2200 0 : for (iterator it = begin(); it != end(); ++it)
2201 0 : it->UpdateMoveTab(rCxt);
2202 0 : }
2203 :
2204 0 : void ScConditionalFormatList::RenameCellStyle( const OUString& rOld, const OUString& rNew )
2205 : {
2206 0 : for( iterator itr = begin(); itr != end(); ++itr)
2207 0 : itr->RenameCellStyle(rOld,rNew);
2208 0 : }
2209 :
2210 0 : bool ScConditionalFormatList::CheckAllEntries()
2211 : {
2212 0 : bool bValid = true;
2213 :
2214 : // need to check which must be deleted
2215 0 : iterator itr = begin();
2216 0 : while(itr != end())
2217 : {
2218 0 : if(itr->GetRange().empty())
2219 : {
2220 0 : bValid = false;
2221 0 : maConditionalFormats.erase(itr++);
2222 : }
2223 : else
2224 0 : ++itr;
2225 : }
2226 :
2227 0 : return bValid;
2228 : }
2229 :
2230 0 : void ScConditionalFormatList::DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
2231 : {
2232 0 : for( iterator itr = begin(); itr != end(); ++itr)
2233 0 : itr->DeleteArea( nCol1, nRow1, nCol2, nRow2 );
2234 :
2235 0 : CheckAllEntries();
2236 0 : }
2237 :
2238 0 : void ScConditionalFormatList::SourceChanged( const ScAddress& rAddr )
2239 : {
2240 0 : for( iterator itr = begin(); itr != end(); ++itr)
2241 0 : itr->SourceChanged( rAddr );
2242 0 : }
2243 :
2244 0 : ScConditionalFormatList::iterator ScConditionalFormatList::begin()
2245 : {
2246 0 : return maConditionalFormats.begin();
2247 : }
2248 :
2249 0 : ScConditionalFormatList::const_iterator ScConditionalFormatList::begin() const
2250 : {
2251 0 : return maConditionalFormats.begin();
2252 : }
2253 :
2254 0 : ScConditionalFormatList::iterator ScConditionalFormatList::end()
2255 : {
2256 0 : return maConditionalFormats.end();
2257 : }
2258 :
2259 0 : ScConditionalFormatList::const_iterator ScConditionalFormatList::end() const
2260 : {
2261 0 : return maConditionalFormats.end();
2262 : }
2263 :
2264 0 : size_t ScConditionalFormatList::size() const
2265 : {
2266 0 : return maConditionalFormats.size();
2267 : }
2268 :
2269 0 : void ScConditionalFormatList::erase( sal_uLong nIndex )
2270 : {
2271 0 : for( iterator itr = begin(); itr != end(); ++itr )
2272 : {
2273 0 : if( itr->GetKey() == nIndex )
2274 : {
2275 0 : maConditionalFormats.erase(itr);
2276 0 : break;
2277 : }
2278 : }
2279 0 : }
2280 :
2281 0 : void ScConditionalFormatList::startRendering()
2282 : {
2283 0 : for(iterator itr = begin(); itr != end(); ++itr)
2284 : {
2285 0 : itr->startRendering();
2286 : }
2287 0 : }
2288 :
2289 0 : void ScConditionalFormatList::endRendering()
2290 : {
2291 0 : for(iterator itr = begin(); itr != end(); ++itr)
2292 : {
2293 0 : itr->endRendering();
2294 : }
2295 0 : }
2296 :
2297 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|