xref: /aoo41x/main/sc/source/core/data/conditio.cxx (revision 6dfe295f)
1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5b3f79822SAndrew Rist  * distributed with this work for additional information
6b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10b3f79822SAndrew Rist  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12b3f79822SAndrew Rist  *
13b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17b3f79822SAndrew Rist  * specific language governing permissions and limitations
18b3f79822SAndrew Rist  * under the License.
19b3f79822SAndrew Rist  *
20b3f79822SAndrew Rist  *************************************************************/
21b3f79822SAndrew Rist 
22b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir 
29cdf0e10cSrcweir //------------------------------------------------------------------
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include "scitems.hxx"
32cdf0e10cSrcweir #include <sfx2/objsh.hxx>
33cdf0e10cSrcweir #include <svl/itemset.hxx>
34cdf0e10cSrcweir #include <svl/zforlist.hxx>
35cdf0e10cSrcweir #include <rtl/math.hxx>
36cdf0e10cSrcweir #include <unotools/collatorwrapper.hxx>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include "conditio.hxx"
39cdf0e10cSrcweir #include "cell.hxx"
40cdf0e10cSrcweir #include "document.hxx"
41cdf0e10cSrcweir #include "hints.hxx"
42cdf0e10cSrcweir #include "compiler.hxx"
43cdf0e10cSrcweir #include "rechead.hxx"
44cdf0e10cSrcweir #include "rangelst.hxx"
45cdf0e10cSrcweir #include "stlpool.hxx"
46cdf0e10cSrcweir #include "rangenam.hxx"
47cdf0e10cSrcweir 
48cdf0e10cSrcweir using namespace formula;
49cdf0e10cSrcweir //------------------------------------------------------------------------
50cdf0e10cSrcweir 
51cdf0e10cSrcweir SV_IMPL_OP_PTRARR_SORT( ScConditionalFormats_Impl, ScConditionalFormatPtr );
52cdf0e10cSrcweir 
53cdf0e10cSrcweir //------------------------------------------------------------------------
54cdf0e10cSrcweir 
lcl_HasRelRef(ScDocument * pDoc,ScTokenArray * pFormula,sal_uInt16 nRecursion=0)55cdf0e10cSrcweir sal_Bool lcl_HasRelRef( ScDocument* pDoc, ScTokenArray* pFormula, sal_uInt16 nRecursion = 0 )
56cdf0e10cSrcweir {
57cdf0e10cSrcweir 	if (pFormula)
58cdf0e10cSrcweir 	{
59cdf0e10cSrcweir 		pFormula->Reset();
60cdf0e10cSrcweir 		FormulaToken* t;
61cdf0e10cSrcweir         for( t = pFormula->Next(); t; t = pFormula->Next() )
62cdf0e10cSrcweir 		{
63cdf0e10cSrcweir             switch( t->GetType() )
64cdf0e10cSrcweir             {
65cdf0e10cSrcweir                 case svDoubleRef:
66cdf0e10cSrcweir                 {
67cdf0e10cSrcweir                     ScSingleRefData& rRef2 = static_cast<ScToken*>(t)->GetDoubleRef().Ref2;
68cdf0e10cSrcweir                     if ( rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel() )
69cdf0e10cSrcweir                         return sal_True;
70cdf0e10cSrcweir                 }
71cdf0e10cSrcweir                 // fall through
72cdf0e10cSrcweir 
73cdf0e10cSrcweir                 case svSingleRef:
74cdf0e10cSrcweir                 {
75cdf0e10cSrcweir                     ScSingleRefData& rRef1 = static_cast<ScToken*>(t)->GetSingleRef();
76cdf0e10cSrcweir                     if ( rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel() )
77cdf0e10cSrcweir                         return sal_True;
78cdf0e10cSrcweir                 }
79cdf0e10cSrcweir                 break;
80cdf0e10cSrcweir 
81cdf0e10cSrcweir                 case svIndex:
82cdf0e10cSrcweir                 {
83cdf0e10cSrcweir                     if( t->GetOpCode() == ocName )      // DB areas always absolute
84cdf0e10cSrcweir                         if( ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( t->GetIndex() ) )
85cdf0e10cSrcweir                             if( (nRecursion < 42) && lcl_HasRelRef( pDoc, pRangeData->GetCode(), nRecursion + 1 ) )
86cdf0e10cSrcweir                                 return sal_True;
87cdf0e10cSrcweir                 }
88cdf0e10cSrcweir                 break;
89cdf0e10cSrcweir 
90cdf0e10cSrcweir                 // #i34474# function result dependent on cell position
91cdf0e10cSrcweir                 case svByte:
92cdf0e10cSrcweir                 {
93cdf0e10cSrcweir                     switch( t->GetOpCode() )
94cdf0e10cSrcweir                     {
95cdf0e10cSrcweir                         case ocRow:     // ROW() returns own row index
96cdf0e10cSrcweir                         case ocColumn:  // COLUMN() returns own column index
97cdf0e10cSrcweir                         case ocTable:   // SHEET() returns own sheet index
98cdf0e10cSrcweir                         case ocCell:    // CELL() may return own cell address
99cdf0e10cSrcweir                             return sal_True;
100cdf0e10cSrcweir //                        break;
101cdf0e10cSrcweir                         default:
102cdf0e10cSrcweir                         {
103cdf0e10cSrcweir                             // added to avoid warnings
104cdf0e10cSrcweir                         }
105cdf0e10cSrcweir                     }
106cdf0e10cSrcweir                 }
107cdf0e10cSrcweir                 break;
108cdf0e10cSrcweir 
109cdf0e10cSrcweir                 default:
110cdf0e10cSrcweir                 {
111cdf0e10cSrcweir                     // added to avoid warnings
112cdf0e10cSrcweir                 }
113cdf0e10cSrcweir             }
114cdf0e10cSrcweir 		}
115cdf0e10cSrcweir 	}
116cdf0e10cSrcweir 	return sal_False;
117cdf0e10cSrcweir }
118cdf0e10cSrcweir 
ScConditionEntry(const ScConditionEntry & r)119cdf0e10cSrcweir ScConditionEntry::ScConditionEntry( const ScConditionEntry& r ) :
120cdf0e10cSrcweir 	eOp(r.eOp),
121cdf0e10cSrcweir 	nOptions(r.nOptions),
122cdf0e10cSrcweir 	nVal1(r.nVal1),
123cdf0e10cSrcweir 	nVal2(r.nVal2),
124cdf0e10cSrcweir 	aStrVal1(r.aStrVal1),
125cdf0e10cSrcweir 	aStrVal2(r.aStrVal2),
126cdf0e10cSrcweir     aStrNmsp1(r.aStrNmsp1),
127cdf0e10cSrcweir     aStrNmsp2(r.aStrNmsp2),
128cdf0e10cSrcweir     eTempGrammar1(r.eTempGrammar1),
129cdf0e10cSrcweir     eTempGrammar2(r.eTempGrammar2),
130cdf0e10cSrcweir 	bIsStr1(r.bIsStr1),
131cdf0e10cSrcweir 	bIsStr2(r.bIsStr2),
132cdf0e10cSrcweir 	pFormula1(NULL),
133cdf0e10cSrcweir 	pFormula2(NULL),
134cdf0e10cSrcweir 	aSrcPos(r.aSrcPos),
135cdf0e10cSrcweir     aSrcString(r.aSrcString),
136cdf0e10cSrcweir 	pFCell1(NULL),
137cdf0e10cSrcweir 	pFCell2(NULL),
138cdf0e10cSrcweir 	pDoc(r.pDoc),
139cdf0e10cSrcweir 	bRelRef1(r.bRelRef1),
140cdf0e10cSrcweir 	bRelRef2(r.bRelRef2),
141cdf0e10cSrcweir 	bFirstRun(sal_True)
142cdf0e10cSrcweir {
143cdf0e10cSrcweir 	//	ScTokenArray copy ctor erzeugt flache Kopie
144cdf0e10cSrcweir 
145cdf0e10cSrcweir 	if (r.pFormula1)
146cdf0e10cSrcweir 		pFormula1 = new ScTokenArray( *r.pFormula1 );
147cdf0e10cSrcweir 	if (r.pFormula2)
148cdf0e10cSrcweir 		pFormula2 = new ScTokenArray( *r.pFormula2 );
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 	//	Formelzellen werden erst bei IsValid angelegt
151cdf0e10cSrcweir }
152cdf0e10cSrcweir 
ScConditionEntry(ScDocument * pDocument,const ScConditionEntry & r)153cdf0e10cSrcweir ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntry& r ) :
154cdf0e10cSrcweir 	eOp(r.eOp),
155cdf0e10cSrcweir 	nOptions(r.nOptions),
156cdf0e10cSrcweir 	nVal1(r.nVal1),
157cdf0e10cSrcweir 	nVal2(r.nVal2),
158cdf0e10cSrcweir 	aStrVal1(r.aStrVal1),
159cdf0e10cSrcweir 	aStrVal2(r.aStrVal2),
160cdf0e10cSrcweir     aStrNmsp1(r.aStrNmsp1),
161cdf0e10cSrcweir     aStrNmsp2(r.aStrNmsp2),
162cdf0e10cSrcweir     eTempGrammar1(r.eTempGrammar1),
163cdf0e10cSrcweir     eTempGrammar2(r.eTempGrammar2),
164cdf0e10cSrcweir 	bIsStr1(r.bIsStr1),
165cdf0e10cSrcweir 	bIsStr2(r.bIsStr2),
166cdf0e10cSrcweir 	pFormula1(NULL),
167cdf0e10cSrcweir 	pFormula2(NULL),
168cdf0e10cSrcweir 	aSrcPos(r.aSrcPos),
169cdf0e10cSrcweir     aSrcString(r.aSrcString),
170cdf0e10cSrcweir 	pFCell1(NULL),
171cdf0e10cSrcweir 	pFCell2(NULL),
172cdf0e10cSrcweir 	pDoc(pDocument),
173cdf0e10cSrcweir 	bRelRef1(r.bRelRef1),
174cdf0e10cSrcweir 	bRelRef2(r.bRelRef2),
175cdf0e10cSrcweir 	bFirstRun(sal_True)
176cdf0e10cSrcweir {
177cdf0e10cSrcweir 	// echte Kopie der Formeln (fuer Ref-Undo)
178cdf0e10cSrcweir 
179cdf0e10cSrcweir 	if (r.pFormula1)
180cdf0e10cSrcweir 		pFormula1 = r.pFormula1->Clone();
181cdf0e10cSrcweir 	if (r.pFormula2)
182cdf0e10cSrcweir 		pFormula2 = r.pFormula2->Clone();
183cdf0e10cSrcweir 
184cdf0e10cSrcweir 	//	Formelzellen werden erst bei IsValid angelegt
185cdf0e10cSrcweir 	//!	im Clipboard nicht - dann vorher interpretieren !!!
186cdf0e10cSrcweir }
187cdf0e10cSrcweir 
ScConditionEntry(ScConditionMode eOper,const String & rExpr1,const String & rExpr2,ScDocument * pDocument,const ScAddress & rPos,const String & rExprNmsp1,const String & rExprNmsp2,FormulaGrammar::Grammar eGrammar1,FormulaGrammar::Grammar eGrammar2)188cdf0e10cSrcweir ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
189cdf0e10cSrcweir         const String& rExpr1, const String& rExpr2, ScDocument* pDocument, const ScAddress& rPos,
190cdf0e10cSrcweir         const String& rExprNmsp1, const String& rExprNmsp2,
191cdf0e10cSrcweir         FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2 ) :
192cdf0e10cSrcweir 	eOp(eOper),
193cdf0e10cSrcweir 	nOptions(0),	// spaeter...
194cdf0e10cSrcweir 	nVal1(0.0),
195cdf0e10cSrcweir 	nVal2(0.0),
196cdf0e10cSrcweir     aStrNmsp1(rExprNmsp1),
197cdf0e10cSrcweir     aStrNmsp2(rExprNmsp2),
198cdf0e10cSrcweir     eTempGrammar1(eGrammar1),
199cdf0e10cSrcweir     eTempGrammar2(eGrammar2),
200cdf0e10cSrcweir 	bIsStr1(sal_False),
201cdf0e10cSrcweir 	bIsStr2(sal_False),
202cdf0e10cSrcweir 	pFormula1(NULL),
203cdf0e10cSrcweir 	pFormula2(NULL),
204cdf0e10cSrcweir 	aSrcPos(rPos),
205cdf0e10cSrcweir 	pFCell1(NULL),
206cdf0e10cSrcweir 	pFCell2(NULL),
207cdf0e10cSrcweir 	pDoc(pDocument),
208cdf0e10cSrcweir 	bRelRef1(sal_False),
209cdf0e10cSrcweir 	bRelRef2(sal_False),
210cdf0e10cSrcweir 	bFirstRun(sal_True)
211cdf0e10cSrcweir {
212cdf0e10cSrcweir     Compile( rExpr1, rExpr2, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2, sal_False );
213cdf0e10cSrcweir 
214cdf0e10cSrcweir 	//	Formelzellen werden erst bei IsValid angelegt
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
ScConditionEntry(ScConditionMode eOper,const ScTokenArray * pArr1,const ScTokenArray * pArr2,ScDocument * pDocument,const ScAddress & rPos)217cdf0e10cSrcweir ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
218cdf0e10cSrcweir 								const ScTokenArray* pArr1, const ScTokenArray* pArr2,
219cdf0e10cSrcweir 								ScDocument* pDocument, const ScAddress& rPos ) :
220cdf0e10cSrcweir 	eOp(eOper),
221cdf0e10cSrcweir 	nOptions(0),	// spaeter...
222cdf0e10cSrcweir 	nVal1(0.0),
223cdf0e10cSrcweir 	nVal2(0.0),
224cdf0e10cSrcweir     eTempGrammar1(FormulaGrammar::GRAM_DEFAULT),
225cdf0e10cSrcweir     eTempGrammar2(FormulaGrammar::GRAM_DEFAULT),
226cdf0e10cSrcweir 	bIsStr1(sal_False),
227cdf0e10cSrcweir 	bIsStr2(sal_False),
228cdf0e10cSrcweir 	pFormula1(NULL),
229cdf0e10cSrcweir 	pFormula2(NULL),
230cdf0e10cSrcweir 	aSrcPos(rPos),
231cdf0e10cSrcweir 	pFCell1(NULL),
232cdf0e10cSrcweir 	pFCell2(NULL),
233cdf0e10cSrcweir 	pDoc(pDocument),
234cdf0e10cSrcweir 	bRelRef1(sal_False),
235cdf0e10cSrcweir 	bRelRef2(sal_False),
236cdf0e10cSrcweir 	bFirstRun(sal_True)
237cdf0e10cSrcweir {
238cdf0e10cSrcweir 	if ( pArr1 )
239cdf0e10cSrcweir 	{
240cdf0e10cSrcweir 		pFormula1 = new ScTokenArray( *pArr1 );
241cdf0e10cSrcweir 		if ( pFormula1->GetLen() == 1 )
242cdf0e10cSrcweir 		{
243cdf0e10cSrcweir 			// einzelne (konstante Zahl) ?
244cdf0e10cSrcweir 			FormulaToken* pToken = pFormula1->First();
245cdf0e10cSrcweir 			if ( pToken->GetOpCode() == ocPush )
246cdf0e10cSrcweir 			{
247cdf0e10cSrcweir 				if ( pToken->GetType() == svDouble )
248cdf0e10cSrcweir 				{
249cdf0e10cSrcweir 					nVal1 = pToken->GetDouble();
250cdf0e10cSrcweir 					DELETEZ(pFormula1);				// nicht als Formel merken
251cdf0e10cSrcweir 				}
252cdf0e10cSrcweir 				else if ( pToken->GetType() == svString )
253cdf0e10cSrcweir 				{
254cdf0e10cSrcweir 					bIsStr1 = sal_True;
255cdf0e10cSrcweir 					aStrVal1 = pToken->GetString();
256cdf0e10cSrcweir 					DELETEZ(pFormula1);				// nicht als Formel merken
257cdf0e10cSrcweir 				}
258cdf0e10cSrcweir 			}
259cdf0e10cSrcweir 		}
260cdf0e10cSrcweir 		bRelRef1 = lcl_HasRelRef( pDoc, pFormula1 );
261cdf0e10cSrcweir 	}
262cdf0e10cSrcweir 	if ( pArr2 )
263cdf0e10cSrcweir 	{
264cdf0e10cSrcweir 		pFormula2 = new ScTokenArray( *pArr2 );
265cdf0e10cSrcweir 		if ( pFormula2->GetLen() == 1 )
266cdf0e10cSrcweir 		{
267cdf0e10cSrcweir 			// einzelne (konstante Zahl) ?
268cdf0e10cSrcweir 			FormulaToken* pToken = pFormula2->First();
269cdf0e10cSrcweir 			if ( pToken->GetOpCode() == ocPush )
270cdf0e10cSrcweir 			{
271cdf0e10cSrcweir 				if ( pToken->GetType() == svDouble )
272cdf0e10cSrcweir 				{
273cdf0e10cSrcweir 					nVal2 = pToken->GetDouble();
274cdf0e10cSrcweir 					DELETEZ(pFormula2);				// nicht als Formel merken
275cdf0e10cSrcweir 				}
276cdf0e10cSrcweir 				else if ( pToken->GetType() == svString )
277cdf0e10cSrcweir 				{
278cdf0e10cSrcweir 					bIsStr2 = sal_True;
279cdf0e10cSrcweir 					aStrVal2 = pToken->GetString();
280cdf0e10cSrcweir 					DELETEZ(pFormula2);				// nicht als Formel merken
281cdf0e10cSrcweir 				}
282cdf0e10cSrcweir 			}
283cdf0e10cSrcweir 		}
284cdf0e10cSrcweir 		bRelRef2 = lcl_HasRelRef( pDoc, pFormula2 );
285cdf0e10cSrcweir 	}
286cdf0e10cSrcweir 
287cdf0e10cSrcweir 	//	formula cells are created at IsValid
288cdf0e10cSrcweir }
289cdf0e10cSrcweir 
~ScConditionEntry()290cdf0e10cSrcweir ScConditionEntry::~ScConditionEntry()
291cdf0e10cSrcweir {
292cdf0e10cSrcweir 	delete pFCell1;
293cdf0e10cSrcweir 	delete pFCell2;
294cdf0e10cSrcweir 
295cdf0e10cSrcweir 	delete pFormula1;
296cdf0e10cSrcweir 	delete pFormula2;
297cdf0e10cSrcweir }
298cdf0e10cSrcweir 
Compile(const String & rExpr1,const String & rExpr2,const String & rExprNmsp1,const String & rExprNmsp2,FormulaGrammar::Grammar eGrammar1,FormulaGrammar::Grammar eGrammar2,sal_Bool bTextToReal)299cdf0e10cSrcweir void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2,
300cdf0e10cSrcweir         const String& rExprNmsp1, const String& rExprNmsp2,
301cdf0e10cSrcweir         FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2, sal_Bool bTextToReal )
302cdf0e10cSrcweir {
303cdf0e10cSrcweir 	if ( rExpr1.Len() || rExpr2.Len() )
304cdf0e10cSrcweir 	{
305cdf0e10cSrcweir 		ScCompiler aComp( pDoc, aSrcPos );
306cdf0e10cSrcweir 
307cdf0e10cSrcweir 		if ( rExpr1.Len() )
308cdf0e10cSrcweir 		{
309cdf0e10cSrcweir             aComp.SetGrammar( eGrammar1 );
310cdf0e10cSrcweir 			if ( pDoc->IsImportingXML() && !bTextToReal )
311cdf0e10cSrcweir 			{
312cdf0e10cSrcweir 				//	temporary formula string as string tokens
313cdf0e10cSrcweir 				//!	merge with lcl_ScDocFunc_CreateTokenArrayXML
314cdf0e10cSrcweir 				pFormula1 = new ScTokenArray;
315cdf0e10cSrcweir 				pFormula1->AddString( rExpr1 );
316cdf0e10cSrcweir 				// bRelRef1 is set when the formula is compiled again (CompileXML)
317cdf0e10cSrcweir 			}
318cdf0e10cSrcweir 			else
319cdf0e10cSrcweir 			{
320cdf0e10cSrcweir                 pFormula1 = aComp.CompileString( rExpr1, rExprNmsp1 );
321cdf0e10cSrcweir 				if ( pFormula1->GetLen() == 1 )
322cdf0e10cSrcweir 				{
323cdf0e10cSrcweir 					// einzelne (konstante Zahl) ?
324cdf0e10cSrcweir 					FormulaToken* pToken = pFormula1->First();
325cdf0e10cSrcweir 					if ( pToken->GetOpCode() == ocPush )
326cdf0e10cSrcweir 					{
327cdf0e10cSrcweir 						if ( pToken->GetType() == svDouble )
328cdf0e10cSrcweir 						{
329cdf0e10cSrcweir 							nVal1 = pToken->GetDouble();
330cdf0e10cSrcweir 							DELETEZ(pFormula1);				// nicht als Formel merken
331cdf0e10cSrcweir 						}
332cdf0e10cSrcweir 						else if ( pToken->GetType() == svString )
333cdf0e10cSrcweir 						{
334cdf0e10cSrcweir 							bIsStr1 = sal_True;
335cdf0e10cSrcweir 							aStrVal1 = pToken->GetString();
336cdf0e10cSrcweir 							DELETEZ(pFormula1);				// nicht als Formel merken
337cdf0e10cSrcweir 						}
338cdf0e10cSrcweir 					}
339cdf0e10cSrcweir 				}
340cdf0e10cSrcweir 				bRelRef1 = lcl_HasRelRef( pDoc, pFormula1 );
341cdf0e10cSrcweir 			}
342cdf0e10cSrcweir 		}
343cdf0e10cSrcweir 
344cdf0e10cSrcweir 		if ( rExpr2.Len() )
345cdf0e10cSrcweir 		{
346cdf0e10cSrcweir             aComp.SetGrammar( eGrammar2 );
347cdf0e10cSrcweir 			if ( pDoc->IsImportingXML() && !bTextToReal )
348cdf0e10cSrcweir 			{
349cdf0e10cSrcweir 				//	temporary formula string as string tokens
350cdf0e10cSrcweir 				//!	merge with lcl_ScDocFunc_CreateTokenArrayXML
351cdf0e10cSrcweir 				pFormula2 = new ScTokenArray;
352cdf0e10cSrcweir 				pFormula2->AddString( rExpr2 );
353cdf0e10cSrcweir 				// bRelRef2 is set when the formula is compiled again (CompileXML)
354cdf0e10cSrcweir 			}
355cdf0e10cSrcweir 			else
356cdf0e10cSrcweir 			{
357cdf0e10cSrcweir                 pFormula2 = aComp.CompileString( rExpr2, rExprNmsp2 );
358cdf0e10cSrcweir 				if ( pFormula2->GetLen() == 1 )
359cdf0e10cSrcweir 				{
360cdf0e10cSrcweir 					// einzelne (konstante Zahl) ?
361cdf0e10cSrcweir 					FormulaToken* pToken = pFormula2->First();
362cdf0e10cSrcweir 					if ( pToken->GetOpCode() == ocPush )
363cdf0e10cSrcweir 					{
364cdf0e10cSrcweir 						if ( pToken->GetType() == svDouble )
365cdf0e10cSrcweir 						{
366cdf0e10cSrcweir 							nVal2 = pToken->GetDouble();
367cdf0e10cSrcweir 							DELETEZ(pFormula2);				// nicht als Formel merken
368cdf0e10cSrcweir 						}
369cdf0e10cSrcweir 						else if ( pToken->GetType() == svString )
370cdf0e10cSrcweir 						{
371cdf0e10cSrcweir 							bIsStr2 = sal_True;
372cdf0e10cSrcweir 							aStrVal2 = pToken->GetString();
373cdf0e10cSrcweir 							DELETEZ(pFormula2);				// nicht als Formel merken
374cdf0e10cSrcweir 						}
375cdf0e10cSrcweir 					}
376cdf0e10cSrcweir 				}
377cdf0e10cSrcweir 				bRelRef2 = lcl_HasRelRef( pDoc, pFormula2 );
378cdf0e10cSrcweir 			}
379cdf0e10cSrcweir 		}
380cdf0e10cSrcweir 	}
381cdf0e10cSrcweir }
382cdf0e10cSrcweir 
MakeCells(const ScAddress & rPos)383cdf0e10cSrcweir void ScConditionEntry::MakeCells( const ScAddress& rPos )			// Formelzellen anlegen
384cdf0e10cSrcweir {
385cdf0e10cSrcweir 	if ( !pDoc->IsClipOrUndo() )			// nie im Clipboard rechnen!
386cdf0e10cSrcweir 	{
387cdf0e10cSrcweir 		if ( pFormula1 && !pFCell1 && !bRelRef1 )
388cdf0e10cSrcweir 		{
389cdf0e10cSrcweir 			pFCell1 = new ScFormulaCell( pDoc, rPos, pFormula1 );
390cdf0e10cSrcweir 			pFCell1->StartListeningTo( pDoc );
391cdf0e10cSrcweir 		}
392cdf0e10cSrcweir 
393cdf0e10cSrcweir 		if ( pFormula2 && !pFCell2 && !bRelRef2 )
394cdf0e10cSrcweir 		{
395cdf0e10cSrcweir 			pFCell2 = new ScFormulaCell( pDoc, rPos, pFormula2 );
396cdf0e10cSrcweir 			pFCell2->StartListeningTo( pDoc );
397cdf0e10cSrcweir 		}
398cdf0e10cSrcweir 	}
399cdf0e10cSrcweir }
400cdf0e10cSrcweir 
SetIgnoreBlank(sal_Bool bSet)401cdf0e10cSrcweir void ScConditionEntry::SetIgnoreBlank(sal_Bool bSet)
402cdf0e10cSrcweir {
403cdf0e10cSrcweir 	//	Das Bit SC_COND_NOBLANKS wird gesetzt, wenn Blanks nicht ignoriert werden
404cdf0e10cSrcweir 	//	(nur bei Gueltigkeit)
405cdf0e10cSrcweir 
406cdf0e10cSrcweir 	if (bSet)
407cdf0e10cSrcweir 		nOptions &= ~SC_COND_NOBLANKS;
408cdf0e10cSrcweir 	else
409cdf0e10cSrcweir 		nOptions |= SC_COND_NOBLANKS;
410cdf0e10cSrcweir }
411cdf0e10cSrcweir 
CompileAll()412cdf0e10cSrcweir void ScConditionEntry::CompileAll()
413cdf0e10cSrcweir {
414cdf0e10cSrcweir 	//	Formelzellen loeschen, dann wird beim naechsten IsValid neu kompiliert
415cdf0e10cSrcweir 
416cdf0e10cSrcweir 	DELETEZ(pFCell1);
417cdf0e10cSrcweir 	DELETEZ(pFCell2);
418cdf0e10cSrcweir }
419cdf0e10cSrcweir 
CompileXML()420cdf0e10cSrcweir void ScConditionEntry::CompileXML()
421cdf0e10cSrcweir {
422cdf0e10cSrcweir     //  #b4974740# First parse the formula source position if it was stored as text
423cdf0e10cSrcweir 
424cdf0e10cSrcweir     if ( aSrcString.Len() )
425cdf0e10cSrcweir     {
426cdf0e10cSrcweir         ScAddress aNew;
427cdf0e10cSrcweir 		/* XML is always in OOo:A1 format, although R1C1 would be more amenable
428cdf0e10cSrcweir 		 * to compression */
429cdf0e10cSrcweir         if ( aNew.Parse( aSrcString, pDoc ) & SCA_VALID )
430cdf0e10cSrcweir             aSrcPos = aNew;
431cdf0e10cSrcweir         // if the position is invalid, there isn't much we can do at this time
432cdf0e10cSrcweir         aSrcString.Erase();
433cdf0e10cSrcweir     }
434cdf0e10cSrcweir 
435cdf0e10cSrcweir 	//	Convert the text tokens that were created during XML import into real tokens.
436cdf0e10cSrcweir 
437cdf0e10cSrcweir     Compile( GetExpression(aSrcPos, 0, 0, eTempGrammar1),
438cdf0e10cSrcweir              GetExpression(aSrcPos, 1, 0, eTempGrammar2),
439cdf0e10cSrcweir              aStrNmsp1, aStrNmsp2, eTempGrammar1, eTempGrammar2, sal_True );
440cdf0e10cSrcweir }
441cdf0e10cSrcweir 
SetSrcString(const String & rNew)442cdf0e10cSrcweir void ScConditionEntry::SetSrcString( const String& rNew )
443cdf0e10cSrcweir {
444cdf0e10cSrcweir     // aSrcString is only evaluated in CompileXML
445cdf0e10cSrcweir     DBG_ASSERT( pDoc->IsImportingXML(), "SetSrcString is only valid for XML import" );
446cdf0e10cSrcweir 
447cdf0e10cSrcweir     aSrcString = rNew;
448cdf0e10cSrcweir }
449cdf0e10cSrcweir 
SetFormula1(const ScTokenArray & rArray)450cdf0e10cSrcweir void ScConditionEntry::SetFormula1( const ScTokenArray& rArray )
451cdf0e10cSrcweir {
452cdf0e10cSrcweir     DELETEZ( pFormula1 );
453cdf0e10cSrcweir     if( rArray.GetLen() > 0 )
454cdf0e10cSrcweir     {
455cdf0e10cSrcweir         pFormula1 = new ScTokenArray( rArray );
456cdf0e10cSrcweir         bRelRef1 = lcl_HasRelRef( pDoc, pFormula1 );
457cdf0e10cSrcweir     }
458cdf0e10cSrcweir }
459cdf0e10cSrcweir 
SetFormula2(const ScTokenArray & rArray)460cdf0e10cSrcweir void ScConditionEntry::SetFormula2( const ScTokenArray& rArray )
461cdf0e10cSrcweir {
462cdf0e10cSrcweir     DELETEZ( pFormula2 );
463cdf0e10cSrcweir     if( rArray.GetLen() > 0 )
464cdf0e10cSrcweir     {
465cdf0e10cSrcweir         pFormula2 = new ScTokenArray( rArray );
466cdf0e10cSrcweir         bRelRef2 = lcl_HasRelRef( pDoc, pFormula2 );
467cdf0e10cSrcweir     }
468cdf0e10cSrcweir }
469cdf0e10cSrcweir 
lcl_CondUpdateInsertTab(ScTokenArray & rCode,SCTAB nInsTab,SCTAB nPosTab,sal_Bool & rChanged)470cdf0e10cSrcweir void lcl_CondUpdateInsertTab( ScTokenArray& rCode, SCTAB nInsTab, SCTAB nPosTab, sal_Bool& rChanged )
471cdf0e10cSrcweir {
472cdf0e10cSrcweir     //  Insert table: only update absolute table references.
473cdf0e10cSrcweir     //  (Similar to ScCompiler::UpdateInsertTab with bIsName=sal_True, result is the same as for named ranges)
474cdf0e10cSrcweir     //  For deleting, ScCompiler::UpdateDeleteTab is used because of the handling of invalid references.
475cdf0e10cSrcweir 
476cdf0e10cSrcweir     rCode.Reset();
477cdf0e10cSrcweir     ScToken* p = static_cast<ScToken*>(rCode.GetNextReference());
478cdf0e10cSrcweir     while( p )
479cdf0e10cSrcweir     {
480cdf0e10cSrcweir         ScSingleRefData& rRef1 = p->GetSingleRef();
481cdf0e10cSrcweir         if ( !rRef1.IsTabRel() && nInsTab <= rRef1.nTab )
482cdf0e10cSrcweir         {
483cdf0e10cSrcweir             rRef1.nTab += 1;
484cdf0e10cSrcweir             rRef1.nRelTab = rRef1.nTab - nPosTab;
485cdf0e10cSrcweir             rChanged = sal_True;
486cdf0e10cSrcweir         }
487cdf0e10cSrcweir         if( p->GetType() == svDoubleRef )
488cdf0e10cSrcweir         {
489cdf0e10cSrcweir             ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
490cdf0e10cSrcweir             if ( !rRef2.IsTabRel() && nInsTab <= rRef2.nTab )
491cdf0e10cSrcweir             {
492cdf0e10cSrcweir                 rRef2.nTab += 1;
493cdf0e10cSrcweir                 rRef2.nRelTab = rRef2.nTab - nPosTab;
494cdf0e10cSrcweir                 rChanged = sal_True;
495cdf0e10cSrcweir             }
496cdf0e10cSrcweir         }
497cdf0e10cSrcweir         p = static_cast<ScToken*>(rCode.GetNextReference());
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir }
500cdf0e10cSrcweir 
UpdateReference(UpdateRefMode eUpdateRefMode,const ScRange & rRange,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)501cdf0e10cSrcweir void ScConditionEntry::UpdateReference( UpdateRefMode eUpdateRefMode,
502cdf0e10cSrcweir 								const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
503cdf0e10cSrcweir {
504cdf0e10cSrcweir 	sal_Bool bInsertTab = ( eUpdateRefMode == URM_INSDEL && nDz == 1 );
505cdf0e10cSrcweir 	sal_Bool bDeleteTab = ( eUpdateRefMode == URM_INSDEL && nDz == -1 );
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 	sal_Bool bChanged1 = sal_False;
508cdf0e10cSrcweir 	sal_Bool bChanged2 = sal_False;
509cdf0e10cSrcweir 
510cdf0e10cSrcweir 	if (pFormula1)
511cdf0e10cSrcweir 	{
512cdf0e10cSrcweir 		if ( bInsertTab )
513cdf0e10cSrcweir 			lcl_CondUpdateInsertTab( *pFormula1, rRange.aStart.Tab(), aSrcPos.Tab(), bChanged1 );
514cdf0e10cSrcweir 		else
515cdf0e10cSrcweir 		{
516cdf0e10cSrcweir 			ScCompiler aComp( pDoc, aSrcPos, *pFormula1 );
517cdf0e10cSrcweir             aComp.SetGrammar(pDoc->GetGrammar());
518cdf0e10cSrcweir 			if ( bDeleteTab )
519cdf0e10cSrcweir 				aComp.UpdateDeleteTab( rRange.aStart.Tab(), sal_False, sal_True, bChanged1 );
520cdf0e10cSrcweir 			else
521cdf0e10cSrcweir 				aComp.UpdateNameReference( eUpdateRefMode, rRange, nDx, nDy, nDz, bChanged1 );
522cdf0e10cSrcweir 		}
523cdf0e10cSrcweir 
524cdf0e10cSrcweir 		if (bChanged1)
525cdf0e10cSrcweir 			DELETEZ(pFCell1);		// is created again in IsValid
526cdf0e10cSrcweir 	}
527cdf0e10cSrcweir 	if (pFormula2)
528cdf0e10cSrcweir 	{
529cdf0e10cSrcweir 		if ( bInsertTab )
530cdf0e10cSrcweir 			lcl_CondUpdateInsertTab( *pFormula2, rRange.aStart.Tab(), aSrcPos.Tab(), bChanged2 );
531cdf0e10cSrcweir 		else
532cdf0e10cSrcweir 		{
533cdf0e10cSrcweir 			ScCompiler aComp( pDoc, aSrcPos, *pFormula2);
534cdf0e10cSrcweir             aComp.SetGrammar(pDoc->GetGrammar());
535cdf0e10cSrcweir 			if ( bDeleteTab )
536cdf0e10cSrcweir 				aComp.UpdateDeleteTab( rRange.aStart.Tab(), sal_False, sal_True, bChanged2 );
537cdf0e10cSrcweir 			else
538cdf0e10cSrcweir 				aComp.UpdateNameReference( eUpdateRefMode, rRange, nDx, nDy, nDz, bChanged2 );
539cdf0e10cSrcweir 		}
540cdf0e10cSrcweir 
541cdf0e10cSrcweir 		if (bChanged2)
542cdf0e10cSrcweir 			DELETEZ(pFCell2);		// is created again in IsValid
543cdf0e10cSrcweir 	}
544cdf0e10cSrcweir }
545cdf0e10cSrcweir 
UpdateMoveTab(SCTAB nOldPos,SCTAB nNewPos)546cdf0e10cSrcweir void ScConditionEntry::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
547cdf0e10cSrcweir {
548cdf0e10cSrcweir 	if (pFormula1)
549cdf0e10cSrcweir 	{
550cdf0e10cSrcweir 		ScCompiler aComp( pDoc, aSrcPos, *pFormula1);
551cdf0e10cSrcweir         aComp.SetGrammar(pDoc->GetGrammar());
552cdf0e10cSrcweir 		aComp.UpdateMoveTab(nOldPos, nNewPos, sal_True );
553cdf0e10cSrcweir 		DELETEZ(pFCell1);
554cdf0e10cSrcweir 	}
555cdf0e10cSrcweir 	if (pFormula2)
556cdf0e10cSrcweir 	{
557cdf0e10cSrcweir 		ScCompiler aComp( pDoc, aSrcPos, *pFormula2);
558cdf0e10cSrcweir         aComp.SetGrammar(pDoc->GetGrammar());
559cdf0e10cSrcweir 		aComp.UpdateMoveTab(nOldPos, nNewPos, sal_True );
560cdf0e10cSrcweir 		DELETEZ(pFCell2);
561cdf0e10cSrcweir 	}
562cdf0e10cSrcweir }
563cdf0e10cSrcweir 
564cdf0e10cSrcweir //!	als Vergleichsoperator ans TokenArray ???
565cdf0e10cSrcweir 
lcl_IsEqual(const ScTokenArray * pArr1,const ScTokenArray * pArr2)566cdf0e10cSrcweir sal_Bool lcl_IsEqual( const ScTokenArray* pArr1, const ScTokenArray* pArr2 )
567cdf0e10cSrcweir {
568cdf0e10cSrcweir 	//	verglichen wird nur das nicht-UPN Array
569cdf0e10cSrcweir 
570cdf0e10cSrcweir 	if ( pArr1 && pArr2 )
571cdf0e10cSrcweir 	{
572cdf0e10cSrcweir 		sal_uInt16 nLen = pArr1->GetLen();
573cdf0e10cSrcweir 		if ( pArr2->GetLen() != nLen )
574cdf0e10cSrcweir 			return sal_False;
575cdf0e10cSrcweir 
576cdf0e10cSrcweir 		FormulaToken** ppToken1 = pArr1->GetArray();
577cdf0e10cSrcweir 		FormulaToken** ppToken2 = pArr2->GetArray();
578cdf0e10cSrcweir 		for (sal_uInt16 i=0; i<nLen; i++)
579cdf0e10cSrcweir 		{
580cdf0e10cSrcweir 			if ( ppToken1[i] != ppToken2[i] &&
581cdf0e10cSrcweir 				 !(*ppToken1[i] == *ppToken2[i]) )
582cdf0e10cSrcweir 				return sal_False;						// Unterschied
583cdf0e10cSrcweir 		}
584cdf0e10cSrcweir 		return sal_True;					// alle Eintraege gleich
585cdf0e10cSrcweir 	}
586cdf0e10cSrcweir 	else
587cdf0e10cSrcweir 		return !pArr1 && !pArr2;		// beide 0 -> gleich
588cdf0e10cSrcweir }
589cdf0e10cSrcweir 
operator ==(const ScConditionEntry & r) const590cdf0e10cSrcweir int ScConditionEntry::operator== ( const ScConditionEntry& r ) const
591cdf0e10cSrcweir {
592cdf0e10cSrcweir 	sal_Bool bEq = (eOp == r.eOp && nOptions == r.nOptions &&
593cdf0e10cSrcweir 				lcl_IsEqual( pFormula1, r.pFormula1 ) &&
594cdf0e10cSrcweir 				lcl_IsEqual( pFormula2, r.pFormula2 ));
595cdf0e10cSrcweir 	if (bEq)
596cdf0e10cSrcweir 	{
597cdf0e10cSrcweir         // for formulas, the reference positions must be compared, too
598cdf0e10cSrcweir         // (including aSrcString, for inserting the entries during XML import)
599cdf0e10cSrcweir         if ( ( pFormula1 || pFormula2 ) && ( aSrcPos != r.aSrcPos || aSrcString != r.aSrcString ) )
600cdf0e10cSrcweir 			bEq = sal_False;
601cdf0e10cSrcweir 
602cdf0e10cSrcweir 		//	wenn keine Formeln, Werte vergleichen
603cdf0e10cSrcweir 		if ( !pFormula1 && ( nVal1 != r.nVal1 || aStrVal1 != r.aStrVal1 || bIsStr1 != r.bIsStr1 ) )
604cdf0e10cSrcweir 			bEq = sal_False;
605cdf0e10cSrcweir 		if ( !pFormula2 && ( nVal2 != r.nVal2 || aStrVal2 != r.aStrVal2 || bIsStr2 != r.bIsStr2 ) )
606cdf0e10cSrcweir 			bEq = sal_False;
607cdf0e10cSrcweir 	}
608cdf0e10cSrcweir 
609cdf0e10cSrcweir 	return bEq;
610cdf0e10cSrcweir }
611cdf0e10cSrcweir 
Interpret(const ScAddress & rPos)612cdf0e10cSrcweir void ScConditionEntry::Interpret( const ScAddress& rPos )
613cdf0e10cSrcweir {
614cdf0e10cSrcweir 	//	Formelzellen anlegen
615cdf0e10cSrcweir 	//	dabei koennen neue Broadcaster (Note-Zellen) ins Dokument eingefuegt werden !!!!
616cdf0e10cSrcweir 
617cdf0e10cSrcweir 	if ( ( pFormula1 && !pFCell1 ) || ( pFormula2 && !pFCell2 ) )
618cdf0e10cSrcweir 		MakeCells( rPos );
619cdf0e10cSrcweir 
620cdf0e10cSrcweir 	//	Formeln auswerten
621cdf0e10cSrcweir 
622cdf0e10cSrcweir 	sal_Bool bDirty = sal_False;		//! 1 und 2 getrennt ???
623cdf0e10cSrcweir 
624cdf0e10cSrcweir 	ScFormulaCell* pTemp1 = NULL;
625cdf0e10cSrcweir 	ScFormulaCell* pEff1 = pFCell1;
626cdf0e10cSrcweir 	if ( bRelRef1 )
627cdf0e10cSrcweir 	{
628cdf0e10cSrcweir 		pTemp1 = new ScFormulaCell( pDoc, rPos, pFormula1 );	// ohne Listening
629cdf0e10cSrcweir 		pEff1 = pTemp1;
630cdf0e10cSrcweir 	}
631cdf0e10cSrcweir 	if ( pEff1 )
632cdf0e10cSrcweir 	{
633cdf0e10cSrcweir 		if (!pEff1->IsRunning())		// keine 522 erzeugen
634cdf0e10cSrcweir 		{
635cdf0e10cSrcweir 			//!	Changed statt Dirty abfragen !!!
636*6dfe295fSWang Lei 			if (pEff1->GetDirty() && !bRelRef1 && pDoc->GetAutoCalc())
637cdf0e10cSrcweir 				bDirty = sal_True;
638cdf0e10cSrcweir 			if (pEff1->IsValue())
639cdf0e10cSrcweir 			{
640cdf0e10cSrcweir 				bIsStr1 = sal_False;
641cdf0e10cSrcweir 				nVal1 = pEff1->GetValue();
642cdf0e10cSrcweir 				aStrVal1.Erase();
643cdf0e10cSrcweir 			}
644cdf0e10cSrcweir 			else
645cdf0e10cSrcweir 			{
646cdf0e10cSrcweir 				bIsStr1 = sal_True;
647cdf0e10cSrcweir 				pEff1->GetString( aStrVal1 );
648cdf0e10cSrcweir 				nVal1 = 0.0;
649cdf0e10cSrcweir 			}
650cdf0e10cSrcweir 		}
651cdf0e10cSrcweir 	}
652cdf0e10cSrcweir 	delete pTemp1;
653cdf0e10cSrcweir 
654cdf0e10cSrcweir 	ScFormulaCell* pTemp2 = NULL;
655cdf0e10cSrcweir 	ScFormulaCell* pEff2 = pFCell2; //@ 1!=2
656cdf0e10cSrcweir 	if ( bRelRef2 )
657cdf0e10cSrcweir 	{
658cdf0e10cSrcweir 		pTemp2 = new ScFormulaCell( pDoc, rPos, pFormula2 );	// ohne Listening
659cdf0e10cSrcweir 		pEff2 = pTemp2;
660cdf0e10cSrcweir 	}
661cdf0e10cSrcweir 	if ( pEff2 )
662cdf0e10cSrcweir 	{
663cdf0e10cSrcweir 		if (!pEff2->IsRunning())		// keine 522 erzeugen
664cdf0e10cSrcweir 		{
665*6dfe295fSWang Lei 			if (pEff2->GetDirty() && !bRelRef2 && pDoc->GetAutoCalc())
666cdf0e10cSrcweir 				bDirty = sal_True;
667cdf0e10cSrcweir 			if (pEff2->IsValue())
668cdf0e10cSrcweir 			{
669cdf0e10cSrcweir 				bIsStr2 = sal_False;
670cdf0e10cSrcweir 				nVal2 = pEff2->GetValue();
671cdf0e10cSrcweir 				aStrVal2.Erase();
672cdf0e10cSrcweir 			}
673cdf0e10cSrcweir 			else
674cdf0e10cSrcweir 			{
675cdf0e10cSrcweir 				bIsStr2 = sal_True;
676cdf0e10cSrcweir 				pEff2->GetString( aStrVal2 );
677cdf0e10cSrcweir 				nVal2 = 0.0;
678cdf0e10cSrcweir 			}
679cdf0e10cSrcweir 		}
680cdf0e10cSrcweir 	}
681cdf0e10cSrcweir 	delete pTemp2;
682cdf0e10cSrcweir 
683cdf0e10cSrcweir 	//	wenn IsRunning, bleiben die letzten Werte erhalten
684cdf0e10cSrcweir 
685cdf0e10cSrcweir 	if (bDirty && !bFirstRun)
686cdf0e10cSrcweir 	{
687cdf0e10cSrcweir 		// 	bei bedingten Formaten neu painten
688cdf0e10cSrcweir 
689cdf0e10cSrcweir 		DataChanged( NULL );	// alles
690cdf0e10cSrcweir 	}
691cdf0e10cSrcweir 
692cdf0e10cSrcweir 	bFirstRun = sal_False;
693cdf0e10cSrcweir }
694cdf0e10cSrcweir 
IsValid(double nArg) const695cdf0e10cSrcweir sal_Bool ScConditionEntry::IsValid( double nArg ) const
696cdf0e10cSrcweir {
697cdf0e10cSrcweir 	//	Interpret muss schon gerufen sein
698cdf0e10cSrcweir 
699cdf0e10cSrcweir 	if ( bIsStr1 )
700cdf0e10cSrcweir 	{
701cdf0e10cSrcweir 		// wenn auf String getestet wird, bei Zahlen immer sal_False, ausser bei "ungleich"
702cdf0e10cSrcweir 
703cdf0e10cSrcweir 		return ( eOp == SC_COND_NOTEQUAL );
704cdf0e10cSrcweir 	}
705cdf0e10cSrcweir 
706cdf0e10cSrcweir 	if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
707cdf0e10cSrcweir 		if ( bIsStr2 )
708cdf0e10cSrcweir 			return sal_False;
709cdf0e10cSrcweir 
710cdf0e10cSrcweir 	double nComp1 = nVal1;		// Kopie, damit vertauscht werden kann
711cdf0e10cSrcweir 	double nComp2 = nVal2;
712cdf0e10cSrcweir 
713cdf0e10cSrcweir 	if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
714cdf0e10cSrcweir 		if ( nComp1 > nComp2 )
715cdf0e10cSrcweir 		{
716cdf0e10cSrcweir 			//	richtige Reihenfolge fuer Wertebereich
717cdf0e10cSrcweir 			double nTemp = nComp1; nComp1 = nComp2; nComp2 = nTemp;
718cdf0e10cSrcweir 		}
719cdf0e10cSrcweir 
720cdf0e10cSrcweir 	//	Alle Grenzfaelle muessen per ::rtl::math::approxEqual getestet werden!
721cdf0e10cSrcweir 
722cdf0e10cSrcweir 	sal_Bool bValid = sal_False;
723cdf0e10cSrcweir 	switch (eOp)
724cdf0e10cSrcweir 	{
725cdf0e10cSrcweir 		case SC_COND_NONE:
726cdf0e10cSrcweir 			break;					// immer sal_False;
727cdf0e10cSrcweir 		case SC_COND_EQUAL:
728cdf0e10cSrcweir 			bValid = ::rtl::math::approxEqual( nArg, nComp1 );
729cdf0e10cSrcweir 			break;
730cdf0e10cSrcweir 		case SC_COND_NOTEQUAL:
731cdf0e10cSrcweir 			bValid = !::rtl::math::approxEqual( nArg, nComp1 );
732cdf0e10cSrcweir 			break;
733cdf0e10cSrcweir 		case SC_COND_GREATER:
734cdf0e10cSrcweir 			bValid = ( nArg > nComp1 ) && !::rtl::math::approxEqual( nArg, nComp1 );
735cdf0e10cSrcweir 			break;
736cdf0e10cSrcweir 		case SC_COND_EQGREATER:
737cdf0e10cSrcweir 			bValid = ( nArg >= nComp1 ) || ::rtl::math::approxEqual( nArg, nComp1 );
738cdf0e10cSrcweir 			break;
739cdf0e10cSrcweir 		case SC_COND_LESS:
740cdf0e10cSrcweir 			bValid = ( nArg < nComp1 ) && !::rtl::math::approxEqual( nArg, nComp1 );
741cdf0e10cSrcweir 			break;
742cdf0e10cSrcweir 		case SC_COND_EQLESS:
743cdf0e10cSrcweir 			bValid = ( nArg <= nComp1 ) || ::rtl::math::approxEqual( nArg, nComp1 );
744cdf0e10cSrcweir 			break;
745cdf0e10cSrcweir 		case SC_COND_BETWEEN:
746cdf0e10cSrcweir 			bValid = ( nArg >= nComp1 && nArg <= nComp2 ) ||
747cdf0e10cSrcweir 					 ::rtl::math::approxEqual( nArg, nComp1 ) || ::rtl::math::approxEqual( nArg, nComp2 );
748cdf0e10cSrcweir 			break;
749cdf0e10cSrcweir 		case SC_COND_NOTBETWEEN:
750cdf0e10cSrcweir 			bValid = ( nArg < nComp1 || nArg > nComp2 ) &&
751cdf0e10cSrcweir 					 !::rtl::math::approxEqual( nArg, nComp1 ) && !::rtl::math::approxEqual( nArg, nComp2 );
752cdf0e10cSrcweir 			break;
753cdf0e10cSrcweir 		case SC_COND_DIRECT:
754cdf0e10cSrcweir 			bValid = !::rtl::math::approxEqual( nComp1, 0.0 );
755cdf0e10cSrcweir 			break;
756cdf0e10cSrcweir 		default:
757cdf0e10cSrcweir 			DBG_ERROR("unbekannte Operation bei ScConditionEntry");
758cdf0e10cSrcweir 			break;
759cdf0e10cSrcweir 	}
760cdf0e10cSrcweir 	return bValid;
761cdf0e10cSrcweir }
762cdf0e10cSrcweir 
IsValidStr(const String & rArg) const763cdf0e10cSrcweir sal_Bool ScConditionEntry::IsValidStr( const String& rArg ) const
764cdf0e10cSrcweir {
765cdf0e10cSrcweir 	//	Interpret muss schon gerufen sein
766cdf0e10cSrcweir 
767cdf0e10cSrcweir 	if ( eOp == SC_COND_DIRECT )				// Formel ist unabhaengig vom Inhalt
768cdf0e10cSrcweir 		return !::rtl::math::approxEqual( nVal1, 0.0 );
769cdf0e10cSrcweir 
770cdf0e10cSrcweir 	//	Wenn Bedingung Zahl enthaelt, immer sal_False, ausser bei "ungleich"
771cdf0e10cSrcweir 
772cdf0e10cSrcweir 	if ( !bIsStr1 )
773cdf0e10cSrcweir 		return ( eOp == SC_COND_NOTEQUAL );
774cdf0e10cSrcweir 	if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
775cdf0e10cSrcweir 		if ( !bIsStr2 )
776cdf0e10cSrcweir 			return sal_False;
777cdf0e10cSrcweir 
778cdf0e10cSrcweir 	String aUpVal1( aStrVal1 );		//! als Member? (dann auch in Interpret setzen)
779cdf0e10cSrcweir 	String aUpVal2( aStrVal2 );
780cdf0e10cSrcweir 
781cdf0e10cSrcweir 	if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
782cdf0e10cSrcweir 		if ( ScGlobal::GetCollator()->compareString( aUpVal1, aUpVal2 )
783cdf0e10cSrcweir 				== COMPARE_GREATER )
784cdf0e10cSrcweir 		{
785cdf0e10cSrcweir 			//	richtige Reihenfolge fuer Wertebereich
786cdf0e10cSrcweir 			String aTemp( aUpVal1 ); aUpVal1 = aUpVal2; aUpVal2 = aTemp;
787cdf0e10cSrcweir 		}
788cdf0e10cSrcweir 
789cdf0e10cSrcweir 	sal_Bool bValid;
790cdf0e10cSrcweir 	switch ( eOp )
791cdf0e10cSrcweir 	{
792cdf0e10cSrcweir 		case SC_COND_EQUAL:
793cdf0e10cSrcweir 			bValid = (ScGlobal::GetCollator()->compareString(
794cdf0e10cSrcweir 				rArg, aUpVal1 ) == COMPARE_EQUAL);
795cdf0e10cSrcweir 		break;
796cdf0e10cSrcweir 		case SC_COND_NOTEQUAL:
797cdf0e10cSrcweir 			bValid = (ScGlobal::GetCollator()->compareString(
798cdf0e10cSrcweir 				rArg, aUpVal1 ) != COMPARE_EQUAL);
799cdf0e10cSrcweir 		break;
800cdf0e10cSrcweir 		default:
801cdf0e10cSrcweir 		{
802cdf0e10cSrcweir 			sal_Int32 nCompare = ScGlobal::GetCollator()->compareString(
803cdf0e10cSrcweir 				rArg, aUpVal1 );
804cdf0e10cSrcweir 			switch ( eOp )
805cdf0e10cSrcweir 			{
806cdf0e10cSrcweir 				case SC_COND_GREATER:
807cdf0e10cSrcweir 					bValid = ( nCompare == COMPARE_GREATER );
808cdf0e10cSrcweir 					break;
809cdf0e10cSrcweir 				case SC_COND_EQGREATER:
810cdf0e10cSrcweir 					bValid = ( nCompare == COMPARE_EQUAL || nCompare == COMPARE_GREATER );
811cdf0e10cSrcweir 					break;
812cdf0e10cSrcweir 				case SC_COND_LESS:
813cdf0e10cSrcweir 					bValid = ( nCompare == COMPARE_LESS );
814cdf0e10cSrcweir 					break;
815cdf0e10cSrcweir 				case SC_COND_EQLESS:
816cdf0e10cSrcweir 					bValid = ( nCompare == COMPARE_EQUAL || nCompare == COMPARE_LESS );
817cdf0e10cSrcweir 					break;
818cdf0e10cSrcweir 				case SC_COND_BETWEEN:
819cdf0e10cSrcweir 				case SC_COND_NOTBETWEEN:
820cdf0e10cSrcweir 					//	Test auf NOTBETWEEN:
821cdf0e10cSrcweir 					bValid = ( nCompare == COMPARE_LESS ||
822cdf0e10cSrcweir 						ScGlobal::GetCollator()->compareString( rArg,
823cdf0e10cSrcweir 						aUpVal2 ) == COMPARE_GREATER );
824cdf0e10cSrcweir 					if ( eOp == SC_COND_BETWEEN )
825cdf0e10cSrcweir 						bValid = !bValid;
826cdf0e10cSrcweir 					break;
827cdf0e10cSrcweir 				//	SC_COND_DIRECT schon oben abgefragt
828cdf0e10cSrcweir 				default:
829cdf0e10cSrcweir 					DBG_ERROR("unbekannte Operation bei ScConditionEntry");
830cdf0e10cSrcweir 					bValid = sal_False;
831cdf0e10cSrcweir 					break;
832cdf0e10cSrcweir 			}
833cdf0e10cSrcweir 		}
834cdf0e10cSrcweir 	}
835cdf0e10cSrcweir 	return bValid;
836cdf0e10cSrcweir }
837cdf0e10cSrcweir 
IsCellValid(ScBaseCell * pCell,const ScAddress & rPos) const838cdf0e10cSrcweir sal_Bool ScConditionEntry::IsCellValid( ScBaseCell* pCell, const ScAddress& rPos ) const
839cdf0e10cSrcweir {
840cdf0e10cSrcweir 	((ScConditionEntry*)this)->Interpret(rPos);			// Formeln auswerten
841cdf0e10cSrcweir 
842cdf0e10cSrcweir 	double nArg = 0.0;
843cdf0e10cSrcweir 	String aArgStr;
844cdf0e10cSrcweir 	sal_Bool bVal = sal_True;
845cdf0e10cSrcweir 
846cdf0e10cSrcweir 	if ( pCell )
847cdf0e10cSrcweir 	{
848cdf0e10cSrcweir 		CellType eType = pCell->GetCellType();
849cdf0e10cSrcweir 		switch (eType)
850cdf0e10cSrcweir 		{
851cdf0e10cSrcweir 			case CELLTYPE_VALUE:
852cdf0e10cSrcweir 				nArg = ((ScValueCell*)pCell)->GetValue();
853cdf0e10cSrcweir 				break;
854cdf0e10cSrcweir 			case CELLTYPE_FORMULA:
855cdf0e10cSrcweir 				{
856cdf0e10cSrcweir 					ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
857cdf0e10cSrcweir 					bVal = pFCell->IsValue();
858cdf0e10cSrcweir 					if (bVal)
859cdf0e10cSrcweir 						nArg = pFCell->GetValue();
860cdf0e10cSrcweir 					else
861cdf0e10cSrcweir 						pFCell->GetString(aArgStr);
862cdf0e10cSrcweir 				}
863cdf0e10cSrcweir 				break;
864cdf0e10cSrcweir 			case CELLTYPE_STRING:
865cdf0e10cSrcweir 			case CELLTYPE_EDIT:
866cdf0e10cSrcweir 				bVal = sal_False;
867cdf0e10cSrcweir 				if ( eType == CELLTYPE_STRING )
868cdf0e10cSrcweir 					((ScStringCell*)pCell)->GetString(aArgStr);
869cdf0e10cSrcweir 				else
870cdf0e10cSrcweir 					((ScEditCell*)pCell)->GetString(aArgStr);
871cdf0e10cSrcweir 				break;
872cdf0e10cSrcweir 
873cdf0e10cSrcweir 			default:
874cdf0e10cSrcweir 				pCell = NULL;			// Note-Zellen wie leere
875cdf0e10cSrcweir 				break;
876cdf0e10cSrcweir 		}
877cdf0e10cSrcweir 	}
878cdf0e10cSrcweir 
879cdf0e10cSrcweir 	if (!pCell)
880cdf0e10cSrcweir 		if (bIsStr1)
881cdf0e10cSrcweir 			bVal = sal_False;				// leere Zellen je nach Bedingung
882cdf0e10cSrcweir 
883cdf0e10cSrcweir 	if (bVal)
884cdf0e10cSrcweir 		return IsValid( nArg );
885cdf0e10cSrcweir 	else
886cdf0e10cSrcweir 		return IsValidStr( aArgStr );
887cdf0e10cSrcweir }
888cdf0e10cSrcweir 
GetExpression(const ScAddress & rCursor,sal_uInt16 nIndex,sal_uLong nNumFmt,const FormulaGrammar::Grammar eGrammar) const889cdf0e10cSrcweir String ScConditionEntry::GetExpression( const ScAddress& rCursor, sal_uInt16 nIndex,
890cdf0e10cSrcweir 										sal_uLong nNumFmt,
891cdf0e10cSrcweir                                         const FormulaGrammar::Grammar eGrammar ) const
892cdf0e10cSrcweir {
893cdf0e10cSrcweir 	String aRet;
894cdf0e10cSrcweir 
895cdf0e10cSrcweir     if ( FormulaGrammar::isEnglish( eGrammar) && nNumFmt == 0 )
896cdf0e10cSrcweir 		nNumFmt = pDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US );
897cdf0e10cSrcweir 
898cdf0e10cSrcweir 	if ( nIndex==0 )
899cdf0e10cSrcweir 	{
900cdf0e10cSrcweir 		if ( pFormula1 )
901cdf0e10cSrcweir 		{
902cdf0e10cSrcweir 			ScCompiler aComp(pDoc, rCursor, *pFormula1);
903cdf0e10cSrcweir             aComp.SetGrammar(eGrammar);
904cdf0e10cSrcweir 			aComp.CreateStringFromTokenArray( aRet );
905cdf0e10cSrcweir 		}
906cdf0e10cSrcweir 		else if (bIsStr1)
907cdf0e10cSrcweir 		{
908cdf0e10cSrcweir 			aRet = '"';
909cdf0e10cSrcweir 			aRet += aStrVal1;
910cdf0e10cSrcweir 			aRet += '"';
911cdf0e10cSrcweir 		}
912cdf0e10cSrcweir 		else
913cdf0e10cSrcweir 			pDoc->GetFormatTable()->GetInputLineString(nVal1, nNumFmt, aRet);
914cdf0e10cSrcweir 	}
915cdf0e10cSrcweir 	else if ( nIndex==1 )
916cdf0e10cSrcweir 	{
917cdf0e10cSrcweir 		if ( pFormula2 )
918cdf0e10cSrcweir 		{
919cdf0e10cSrcweir 			ScCompiler aComp(pDoc, rCursor, *pFormula2);
920cdf0e10cSrcweir             aComp.SetGrammar(eGrammar);
921cdf0e10cSrcweir 			aComp.CreateStringFromTokenArray( aRet );
922cdf0e10cSrcweir 		}
923cdf0e10cSrcweir 		else if (bIsStr2)
924cdf0e10cSrcweir 		{
925cdf0e10cSrcweir 			aRet = '"';
926cdf0e10cSrcweir 			aRet += aStrVal2;
927cdf0e10cSrcweir 			aRet += '"';
928cdf0e10cSrcweir 		}
929cdf0e10cSrcweir 		else
930cdf0e10cSrcweir 			pDoc->GetFormatTable()->GetInputLineString(nVal2, nNumFmt, aRet);
931cdf0e10cSrcweir 	}
932cdf0e10cSrcweir 	else
933cdf0e10cSrcweir 	{
934cdf0e10cSrcweir 		DBG_ERROR("GetExpression: falscher Index");
935cdf0e10cSrcweir 	}
936cdf0e10cSrcweir 
937cdf0e10cSrcweir 	return aRet;
938cdf0e10cSrcweir }
939cdf0e10cSrcweir 
CreateTokenArry(sal_uInt16 nIndex) const940cdf0e10cSrcweir ScTokenArray* ScConditionEntry::CreateTokenArry( sal_uInt16 nIndex ) const
941cdf0e10cSrcweir {
942cdf0e10cSrcweir     ScTokenArray* pRet = NULL;
943cdf0e10cSrcweir 	ScAddress aAddr;
944cdf0e10cSrcweir 
945cdf0e10cSrcweir 	if ( nIndex==0 )
946cdf0e10cSrcweir 	{
947cdf0e10cSrcweir 		if ( pFormula1 )
948cdf0e10cSrcweir 			pRet = new ScTokenArray( *pFormula1 );
949cdf0e10cSrcweir 		else
950cdf0e10cSrcweir 		{
951cdf0e10cSrcweir 			pRet = new ScTokenArray();
952cdf0e10cSrcweir 			if (bIsStr1)
953cdf0e10cSrcweir 				pRet->AddString( aStrVal1.GetBuffer() );
954cdf0e10cSrcweir 			else
955cdf0e10cSrcweir 				pRet->AddDouble( nVal1 );
956cdf0e10cSrcweir 		}
957cdf0e10cSrcweir 	}
958cdf0e10cSrcweir 	else if ( nIndex==1 )
959cdf0e10cSrcweir 	{
960cdf0e10cSrcweir 		if ( pFormula2 )
961cdf0e10cSrcweir 			pRet = new ScTokenArray( *pFormula2 );
962cdf0e10cSrcweir 		else
963cdf0e10cSrcweir 		{
964cdf0e10cSrcweir 			pRet = new ScTokenArray();
965cdf0e10cSrcweir 			if (bIsStr2)
966cdf0e10cSrcweir 				pRet->AddString( aStrVal2.GetBuffer() );
967cdf0e10cSrcweir 			else
968cdf0e10cSrcweir 				pRet->AddDouble( nVal2 );
969cdf0e10cSrcweir 		}
970cdf0e10cSrcweir 	}
971cdf0e10cSrcweir 	else
972cdf0e10cSrcweir 	{
973cdf0e10cSrcweir 		DBG_ERROR("GetExpression: falscher Index");
974cdf0e10cSrcweir 	}
975cdf0e10cSrcweir 
976cdf0e10cSrcweir 	return pRet;
977cdf0e10cSrcweir }
978cdf0e10cSrcweir 
SourceChanged(const ScAddress & rChanged)979cdf0e10cSrcweir void ScConditionEntry::SourceChanged( const ScAddress& rChanged )
980cdf0e10cSrcweir {
981cdf0e10cSrcweir 	for (sal_uInt16 nPass = 0; nPass < 2; nPass++)
982cdf0e10cSrcweir 	{
983cdf0e10cSrcweir 		ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
984cdf0e10cSrcweir 		if (pFormula)
985cdf0e10cSrcweir 		{
986cdf0e10cSrcweir 			pFormula->Reset();
987cdf0e10cSrcweir 			ScToken* t;
988cdf0e10cSrcweir             while ( ( t = static_cast<ScToken*>(pFormula->GetNextReference()) ) != NULL )
989cdf0e10cSrcweir 			{
990cdf0e10cSrcweir 				SingleDoubleRefProvider aProv( *t );
991cdf0e10cSrcweir 				if ( aProv.Ref1.IsColRel() || aProv.Ref1.IsRowRel() || aProv.Ref1.IsTabRel() ||
992cdf0e10cSrcweir 					 aProv.Ref2.IsColRel() || aProv.Ref2.IsRowRel() || aProv.Ref2.IsTabRel() )
993cdf0e10cSrcweir 				{
994cdf0e10cSrcweir 					//	absolut muss getroffen sein, relativ bestimmt Bereich
995cdf0e10cSrcweir 
996cdf0e10cSrcweir 					sal_Bool bHit = sal_True;
997cdf0e10cSrcweir                     SCsCOL nCol1;
998cdf0e10cSrcweir                     SCsROW nRow1;
999cdf0e10cSrcweir                     SCsTAB nTab1;
1000cdf0e10cSrcweir                     SCsCOL nCol2;
1001cdf0e10cSrcweir                     SCsROW nRow2;
1002cdf0e10cSrcweir                     SCsTAB nTab2;
1003cdf0e10cSrcweir 
1004cdf0e10cSrcweir 					if ( aProv.Ref1.IsColRel() )
1005cdf0e10cSrcweir 						nCol2 = rChanged.Col() - aProv.Ref1.nRelCol;
1006cdf0e10cSrcweir 					else
1007cdf0e10cSrcweir 					{
1008cdf0e10cSrcweir 						bHit &= ( rChanged.Col() >= aProv.Ref1.nCol );
1009cdf0e10cSrcweir 						nCol2 = MAXCOL;
1010cdf0e10cSrcweir 					}
1011cdf0e10cSrcweir 					if ( aProv.Ref1.IsRowRel() )
1012cdf0e10cSrcweir 						nRow2 = rChanged.Row() - aProv.Ref1.nRelRow;
1013cdf0e10cSrcweir 					else
1014cdf0e10cSrcweir 					{
1015cdf0e10cSrcweir 						bHit &= ( rChanged.Row() >= aProv.Ref1.nRow );
1016cdf0e10cSrcweir 						nRow2 = MAXROW;
1017cdf0e10cSrcweir 					}
1018cdf0e10cSrcweir 					if ( aProv.Ref1.IsTabRel() )
1019cdf0e10cSrcweir 						nTab2 = rChanged.Tab() - aProv.Ref1.nRelTab;
1020cdf0e10cSrcweir 					else
1021cdf0e10cSrcweir 					{
1022cdf0e10cSrcweir 						bHit &= ( rChanged.Tab() >= aProv.Ref1.nTab );
1023cdf0e10cSrcweir 						nTab2 = MAXTAB;
1024cdf0e10cSrcweir 					}
1025cdf0e10cSrcweir 
1026cdf0e10cSrcweir 					if ( aProv.Ref2.IsColRel() )
1027cdf0e10cSrcweir 						nCol1 = rChanged.Col() - aProv.Ref2.nRelCol;
1028cdf0e10cSrcweir 					else
1029cdf0e10cSrcweir 					{
1030cdf0e10cSrcweir 						bHit &= ( rChanged.Col() <= aProv.Ref2.nCol );
1031cdf0e10cSrcweir 						nCol1 = 0;
1032cdf0e10cSrcweir 					}
1033cdf0e10cSrcweir 					if ( aProv.Ref2.IsRowRel() )
1034cdf0e10cSrcweir 						nRow1 = rChanged.Row() - aProv.Ref2.nRelRow;
1035cdf0e10cSrcweir 					else
1036cdf0e10cSrcweir 					{
1037cdf0e10cSrcweir 						bHit &= ( rChanged.Row() <= aProv.Ref2.nRow );
1038cdf0e10cSrcweir 						nRow1 = 0;
1039cdf0e10cSrcweir 					}
1040cdf0e10cSrcweir 					if ( aProv.Ref2.IsTabRel() )
1041cdf0e10cSrcweir 						nTab1 = rChanged.Tab() - aProv.Ref2.nRelTab;
1042cdf0e10cSrcweir 					else
1043cdf0e10cSrcweir 					{
1044cdf0e10cSrcweir 						bHit &= ( rChanged.Tab() <= aProv.Ref2.nTab );
1045cdf0e10cSrcweir 						nTab1 = 0;
1046cdf0e10cSrcweir 					}
1047cdf0e10cSrcweir 
1048cdf0e10cSrcweir 					if ( bHit )
1049cdf0e10cSrcweir 					{
1050cdf0e10cSrcweir 						//!	begrenzen
1051cdf0e10cSrcweir 
1052cdf0e10cSrcweir 						ScRange aPaint( nCol1,nRow1,nTab1, nCol2,nRow2,nTab2 );
1053cdf0e10cSrcweir 
1054cdf0e10cSrcweir 						//	kein Paint, wenn es nur die Zelle selber ist
1055cdf0e10cSrcweir 						if ( aPaint.aStart != rChanged || aPaint.aEnd != rChanged )
1056cdf0e10cSrcweir 							DataChanged( &aPaint );
1057cdf0e10cSrcweir 					}
1058cdf0e10cSrcweir 				}
1059cdf0e10cSrcweir 			}
1060cdf0e10cSrcweir 		}
1061cdf0e10cSrcweir 	}
1062cdf0e10cSrcweir }
1063cdf0e10cSrcweir 
GetValidSrcPos() const1064cdf0e10cSrcweir ScAddress ScConditionEntry::GetValidSrcPos() const
1065cdf0e10cSrcweir {
1066cdf0e10cSrcweir     // return a position that's adjusted to allow textual representation of expressions if possible
1067cdf0e10cSrcweir 
1068cdf0e10cSrcweir     SCTAB nMinTab = aSrcPos.Tab();
1069cdf0e10cSrcweir     SCTAB nMaxTab = nMinTab;
1070cdf0e10cSrcweir 
1071cdf0e10cSrcweir     for (sal_uInt16 nPass = 0; nPass < 2; nPass++)
1072cdf0e10cSrcweir     {
1073cdf0e10cSrcweir         ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
1074cdf0e10cSrcweir         if (pFormula)
1075cdf0e10cSrcweir         {
1076cdf0e10cSrcweir             pFormula->Reset();
1077cdf0e10cSrcweir             ScToken* t;
1078cdf0e10cSrcweir             while ( ( t = static_cast<ScToken*>(pFormula->GetNextReference()) ) != NULL )
1079cdf0e10cSrcweir             {
1080cdf0e10cSrcweir                 ScSingleRefData& rRef1 = t->GetSingleRef();
1081cdf0e10cSrcweir                 if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
1082cdf0e10cSrcweir                 {
1083cdf0e10cSrcweir                     if ( rRef1.nTab < nMinTab )
1084cdf0e10cSrcweir                         nMinTab = rRef1.nTab;
1085cdf0e10cSrcweir                     if ( rRef1.nTab > nMaxTab )
1086cdf0e10cSrcweir                         nMaxTab = rRef1.nTab;
1087cdf0e10cSrcweir                 }
1088cdf0e10cSrcweir                 if ( t->GetType() == svDoubleRef )
1089cdf0e10cSrcweir                 {
1090cdf0e10cSrcweir                     ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
1091cdf0e10cSrcweir                     if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
1092cdf0e10cSrcweir                     {
1093cdf0e10cSrcweir                         if ( rRef2.nTab < nMinTab )
1094cdf0e10cSrcweir                             nMinTab = rRef2.nTab;
1095cdf0e10cSrcweir                         if ( rRef2.nTab > nMaxTab )
1096cdf0e10cSrcweir                             nMaxTab = rRef2.nTab;
1097cdf0e10cSrcweir                     }
1098cdf0e10cSrcweir                 }
1099cdf0e10cSrcweir             }
1100cdf0e10cSrcweir         }
1101cdf0e10cSrcweir     }
1102cdf0e10cSrcweir 
1103cdf0e10cSrcweir     ScAddress aValidPos = aSrcPos;
1104cdf0e10cSrcweir     SCTAB nTabCount = pDoc->GetTableCount();
1105cdf0e10cSrcweir     if ( nMaxTab >= nTabCount && nMinTab > 0 )
1106cdf0e10cSrcweir         aValidPos.SetTab( aSrcPos.Tab() - nMinTab );    // so the lowest tab ref will be on 0
1107cdf0e10cSrcweir 
1108cdf0e10cSrcweir     if ( aValidPos.Tab() >= nTabCount )
1109cdf0e10cSrcweir         aValidPos.SetTab( nTabCount - 1 );  // ensure a valid position even if some references will be invalid
1110cdf0e10cSrcweir 
1111cdf0e10cSrcweir     return aValidPos;
1112cdf0e10cSrcweir }
1113cdf0e10cSrcweir 
DataChanged(const ScRange *) const1114cdf0e10cSrcweir void ScConditionEntry::DataChanged( const ScRange* /* pModified */ ) const
1115cdf0e10cSrcweir {
1116cdf0e10cSrcweir 	// nix
1117cdf0e10cSrcweir }
1118cdf0e10cSrcweir 
MarkUsedExternalReferences() const1119cdf0e10cSrcweir bool ScConditionEntry::MarkUsedExternalReferences() const
1120cdf0e10cSrcweir {
1121cdf0e10cSrcweir     bool bAllMarked = false;
1122cdf0e10cSrcweir     for (sal_uInt16 nPass = 0; !bAllMarked && nPass < 2; nPass++)
1123cdf0e10cSrcweir     {
1124cdf0e10cSrcweir         ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
1125cdf0e10cSrcweir         if (pFormula)
1126cdf0e10cSrcweir             bAllMarked = pDoc->MarkUsedExternalReferences( *pFormula);
1127cdf0e10cSrcweir     }
1128cdf0e10cSrcweir     return bAllMarked;
1129cdf0e10cSrcweir }
1130cdf0e10cSrcweir 
1131cdf0e10cSrcweir //------------------------------------------------------------------------
1132cdf0e10cSrcweir 
ScCondFormatEntry(ScConditionMode eOper,const String & rExpr1,const String & rExpr2,ScDocument * pDocument,const ScAddress & rPos,const String & rStyle,const String & rExprNmsp1,const String & rExprNmsp2,FormulaGrammar::Grammar eGrammar1,FormulaGrammar::Grammar eGrammar2)1133cdf0e10cSrcweir ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
1134cdf0e10cSrcweir 										const String& rExpr1, const String& rExpr2,
1135cdf0e10cSrcweir 										ScDocument* pDocument, const ScAddress& rPos,
1136cdf0e10cSrcweir 										const String& rStyle,
1137cdf0e10cSrcweir                                         const String& rExprNmsp1, const String& rExprNmsp2,
1138cdf0e10cSrcweir                                         FormulaGrammar::Grammar eGrammar1,
1139cdf0e10cSrcweir                                         FormulaGrammar::Grammar eGrammar2 ) :
1140cdf0e10cSrcweir     ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2 ),
1141cdf0e10cSrcweir 	aStyleName( rStyle ),
1142cdf0e10cSrcweir 	pParent( NULL )
1143cdf0e10cSrcweir {
1144cdf0e10cSrcweir }
1145cdf0e10cSrcweir 
ScCondFormatEntry(ScConditionMode eOper,const ScTokenArray * pArr1,const ScTokenArray * pArr2,ScDocument * pDocument,const ScAddress & rPos,const String & rStyle)1146cdf0e10cSrcweir ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
1147cdf0e10cSrcweir 										const ScTokenArray* pArr1, const ScTokenArray* pArr2,
1148cdf0e10cSrcweir 										ScDocument* pDocument, const ScAddress& rPos,
1149cdf0e10cSrcweir 										const String& rStyle ) :
1150cdf0e10cSrcweir 	ScConditionEntry( eOper, pArr1, pArr2, pDocument, rPos ),
1151cdf0e10cSrcweir 	aStyleName( rStyle ),
1152cdf0e10cSrcweir 	pParent( NULL )
1153cdf0e10cSrcweir {
1154cdf0e10cSrcweir }
1155cdf0e10cSrcweir 
ScCondFormatEntry(const ScCondFormatEntry & r)1156cdf0e10cSrcweir ScCondFormatEntry::ScCondFormatEntry( const ScCondFormatEntry& r ) :
1157cdf0e10cSrcweir 	ScConditionEntry( r ),
1158cdf0e10cSrcweir 	aStyleName( r.aStyleName ),
1159cdf0e10cSrcweir 	pParent( NULL )
1160cdf0e10cSrcweir {
1161cdf0e10cSrcweir }
1162cdf0e10cSrcweir 
ScCondFormatEntry(ScDocument * pDocument,const ScCondFormatEntry & r)1163cdf0e10cSrcweir ScCondFormatEntry::ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r ) :
1164cdf0e10cSrcweir 	ScConditionEntry( pDocument, r ),
1165cdf0e10cSrcweir 	aStyleName( r.aStyleName ),
1166cdf0e10cSrcweir 	pParent( NULL )
1167cdf0e10cSrcweir {
1168cdf0e10cSrcweir }
1169cdf0e10cSrcweir 
operator ==(const ScCondFormatEntry & r) const1170cdf0e10cSrcweir int ScCondFormatEntry::operator== ( const ScCondFormatEntry& r ) const
1171cdf0e10cSrcweir {
1172cdf0e10cSrcweir 	return ScConditionEntry::operator==( r ) &&
1173cdf0e10cSrcweir 			aStyleName == r.aStyleName;
1174cdf0e10cSrcweir 
1175cdf0e10cSrcweir 	//	Range wird nicht verglichen
1176cdf0e10cSrcweir }
1177cdf0e10cSrcweir 
~ScCondFormatEntry()1178cdf0e10cSrcweir ScCondFormatEntry::~ScCondFormatEntry()
1179cdf0e10cSrcweir {
1180cdf0e10cSrcweir }
1181cdf0e10cSrcweir 
DataChanged(const ScRange * pModified) const1182cdf0e10cSrcweir void ScCondFormatEntry::DataChanged( const ScRange* pModified ) const
1183cdf0e10cSrcweir {
1184cdf0e10cSrcweir 	if ( pParent )
1185cdf0e10cSrcweir 		pParent->DoRepaint( pModified );
1186cdf0e10cSrcweir }
1187cdf0e10cSrcweir 
1188cdf0e10cSrcweir //------------------------------------------------------------------------
1189cdf0e10cSrcweir 
ScConditionalFormat(sal_uInt32 nNewKey,ScDocument * pDocument)1190cdf0e10cSrcweir ScConditionalFormat::ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* pDocument) :
1191cdf0e10cSrcweir 	pDoc( pDocument ),
1192cdf0e10cSrcweir 	pAreas( NULL ),
1193cdf0e10cSrcweir 	nKey( nNewKey ),
1194cdf0e10cSrcweir 	ppEntries( NULL ),
1195cdf0e10cSrcweir 	nEntryCount( 0 )
1196cdf0e10cSrcweir {
1197cdf0e10cSrcweir }
1198cdf0e10cSrcweir 
ScConditionalFormat(const ScConditionalFormat & r)1199cdf0e10cSrcweir ScConditionalFormat::ScConditionalFormat(const ScConditionalFormat& r) :
1200cdf0e10cSrcweir 	pDoc( r.pDoc ),
1201cdf0e10cSrcweir 	pAreas( NULL ),
1202cdf0e10cSrcweir 	nKey( r.nKey ),
1203cdf0e10cSrcweir 	ppEntries( NULL ),
1204cdf0e10cSrcweir 	nEntryCount( r.nEntryCount )
1205cdf0e10cSrcweir {
1206cdf0e10cSrcweir 	if (nEntryCount)
1207cdf0e10cSrcweir 	{
1208cdf0e10cSrcweir 		ppEntries = new ScCondFormatEntry*[nEntryCount];
1209cdf0e10cSrcweir 		for (sal_uInt16 i=0; i<nEntryCount; i++)
1210cdf0e10cSrcweir 		{
1211cdf0e10cSrcweir 			ppEntries[i] = new ScCondFormatEntry(*r.ppEntries[i]);
1212cdf0e10cSrcweir 			ppEntries[i]->SetParent(this);
1213cdf0e10cSrcweir 		}
1214cdf0e10cSrcweir 	}
1215cdf0e10cSrcweir }
1216cdf0e10cSrcweir 
Clone(ScDocument * pNewDoc) const1217cdf0e10cSrcweir ScConditionalFormat* ScConditionalFormat::Clone(ScDocument* pNewDoc) const
1218cdf0e10cSrcweir {
1219cdf0e10cSrcweir 	// echte Kopie der Formeln (fuer Ref-Undo / zwischen Dokumenten)
1220cdf0e10cSrcweir 
1221cdf0e10cSrcweir 	if (!pNewDoc)
1222cdf0e10cSrcweir 		pNewDoc = pDoc;
1223cdf0e10cSrcweir 
1224cdf0e10cSrcweir 	ScConditionalFormat* pNew = new ScConditionalFormat(nKey, pNewDoc);
1225cdf0e10cSrcweir 	DBG_ASSERT(!pNew->ppEntries, "wo kommen die Eintraege her?");
1226cdf0e10cSrcweir 
1227cdf0e10cSrcweir 	if (nEntryCount)
1228cdf0e10cSrcweir 	{
1229cdf0e10cSrcweir 		pNew->ppEntries = new ScCondFormatEntry*[nEntryCount];
1230cdf0e10cSrcweir 		for (sal_uInt16 i=0; i<nEntryCount; i++)
1231cdf0e10cSrcweir 		{
1232cdf0e10cSrcweir 			pNew->ppEntries[i] = new ScCondFormatEntry( pNewDoc, *ppEntries[i] );
1233cdf0e10cSrcweir 			pNew->ppEntries[i]->SetParent(pNew);
1234cdf0e10cSrcweir 		}
1235cdf0e10cSrcweir 		pNew->nEntryCount = nEntryCount;
1236cdf0e10cSrcweir 	}
1237cdf0e10cSrcweir 
1238cdf0e10cSrcweir 	return pNew;
1239cdf0e10cSrcweir }
1240cdf0e10cSrcweir 
EqualEntries(const ScConditionalFormat & r) const1241cdf0e10cSrcweir sal_Bool ScConditionalFormat::EqualEntries( const ScConditionalFormat& r ) const
1242cdf0e10cSrcweir {
1243cdf0e10cSrcweir 	if ( nEntryCount != r.nEntryCount )
1244cdf0e10cSrcweir 		return sal_False;
1245cdf0e10cSrcweir 
1246cdf0e10cSrcweir 	//!	auf gleiche Eintraege in anderer Reihenfolge testen ???
1247cdf0e10cSrcweir 
1248cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1249cdf0e10cSrcweir 		if ( ! (*ppEntries[i] == *r.ppEntries[i]) )
1250cdf0e10cSrcweir 			return sal_False;
1251cdf0e10cSrcweir 
1252cdf0e10cSrcweir 	return sal_True;
1253cdf0e10cSrcweir }
1254cdf0e10cSrcweir 
AddEntry(const ScCondFormatEntry & rNew)1255cdf0e10cSrcweir void ScConditionalFormat::AddEntry( const ScCondFormatEntry& rNew )
1256cdf0e10cSrcweir {
1257cdf0e10cSrcweir 	ScCondFormatEntry** ppNew = new ScCondFormatEntry*[nEntryCount+1];
1258cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1259cdf0e10cSrcweir 		ppNew[i] = ppEntries[i];
1260cdf0e10cSrcweir 	ppNew[nEntryCount] = new ScCondFormatEntry(rNew);
1261cdf0e10cSrcweir 	ppNew[nEntryCount]->SetParent(this);
1262cdf0e10cSrcweir 	++nEntryCount;
1263cdf0e10cSrcweir 	delete[] ppEntries;
1264cdf0e10cSrcweir 	ppEntries = ppNew;
1265cdf0e10cSrcweir }
1266cdf0e10cSrcweir 
~ScConditionalFormat()1267cdf0e10cSrcweir ScConditionalFormat::~ScConditionalFormat()
1268cdf0e10cSrcweir {
1269cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1270cdf0e10cSrcweir 		delete ppEntries[i];
1271cdf0e10cSrcweir 	delete[] ppEntries;
1272cdf0e10cSrcweir 
1273cdf0e10cSrcweir 	delete pAreas;
1274cdf0e10cSrcweir }
1275cdf0e10cSrcweir 
GetEntry(sal_uInt16 nPos) const1276cdf0e10cSrcweir const ScCondFormatEntry* ScConditionalFormat::GetEntry( sal_uInt16 nPos ) const
1277cdf0e10cSrcweir {
1278cdf0e10cSrcweir 	if ( nPos < nEntryCount )
1279cdf0e10cSrcweir 		return ppEntries[nPos];
1280cdf0e10cSrcweir 	else
1281cdf0e10cSrcweir 		return NULL;
1282cdf0e10cSrcweir }
1283cdf0e10cSrcweir 
GetCellStyle(ScBaseCell * pCell,const ScAddress & rPos) const1284cdf0e10cSrcweir const String& ScConditionalFormat::GetCellStyle( ScBaseCell* pCell, const ScAddress& rPos ) const
1285cdf0e10cSrcweir {
1286cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1287cdf0e10cSrcweir 		if ( ppEntries[i]->IsCellValid( pCell, rPos ) )
1288cdf0e10cSrcweir 			return ppEntries[i]->GetStyle();
1289cdf0e10cSrcweir 
1290cdf0e10cSrcweir 	return EMPTY_STRING;
1291cdf0e10cSrcweir }
1292cdf0e10cSrcweir 
lcl_Extend(ScRange & rRange,ScDocument * pDoc,sal_Bool bLines)1293cdf0e10cSrcweir void lcl_Extend( ScRange& rRange, ScDocument* pDoc, sal_Bool bLines )
1294cdf0e10cSrcweir {
1295cdf0e10cSrcweir 	SCTAB nTab = rRange.aStart.Tab();
1296cdf0e10cSrcweir 	DBG_ASSERT(rRange.aEnd.Tab() == nTab, "lcl_Extend - mehrere Tabellen?");
1297cdf0e10cSrcweir 
1298cdf0e10cSrcweir 	SCCOL nStartCol = rRange.aStart.Col();
1299cdf0e10cSrcweir 	SCROW nStartRow = rRange.aStart.Row();
1300cdf0e10cSrcweir 	SCCOL nEndCol = rRange.aEnd.Col();
1301cdf0e10cSrcweir 	SCROW nEndRow = rRange.aEnd.Row();
1302cdf0e10cSrcweir 
1303cdf0e10cSrcweir 	sal_Bool bEx = pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
1304cdf0e10cSrcweir 
1305cdf0e10cSrcweir 	if (bLines)
1306cdf0e10cSrcweir 	{
1307cdf0e10cSrcweir 		if (nStartCol > 0)	  --nStartCol;
1308cdf0e10cSrcweir 		if (nStartRow > 0)	  --nStartRow;
1309cdf0e10cSrcweir 		if (nEndCol < MAXCOL) ++nEndCol;
1310cdf0e10cSrcweir 		if (nEndRow < MAXROW) ++nEndRow;
1311cdf0e10cSrcweir 	}
1312cdf0e10cSrcweir 
1313cdf0e10cSrcweir 	if ( bEx || bLines )
1314cdf0e10cSrcweir 	{
1315cdf0e10cSrcweir 		rRange.aStart.Set( nStartCol, nStartRow, nTab );
1316cdf0e10cSrcweir 		rRange.aEnd.Set( nEndCol, nEndRow, nTab );
1317cdf0e10cSrcweir 	}
1318cdf0e10cSrcweir }
1319cdf0e10cSrcweir 
lcl_CutRange(ScRange & rRange,const ScRange & rOther)1320cdf0e10cSrcweir sal_Bool lcl_CutRange( ScRange& rRange, const ScRange& rOther )
1321cdf0e10cSrcweir {
1322cdf0e10cSrcweir 	rRange.Justify();
1323cdf0e10cSrcweir 	ScRange aCmpRange = rOther;
1324cdf0e10cSrcweir 	aCmpRange.Justify();
1325cdf0e10cSrcweir 
1326cdf0e10cSrcweir 	if ( rRange.aStart.Col() <= aCmpRange.aEnd.Col() &&
1327cdf0e10cSrcweir 		 rRange.aEnd.Col() >= aCmpRange.aStart.Col() &&
1328cdf0e10cSrcweir 		 rRange.aStart.Row() <= aCmpRange.aEnd.Row() &&
1329cdf0e10cSrcweir 		 rRange.aEnd.Row() >= aCmpRange.aStart.Row() &&
1330cdf0e10cSrcweir 		 rRange.aStart.Tab() <= aCmpRange.aEnd.Tab() &&
1331cdf0e10cSrcweir 		 rRange.aEnd.Tab() >= aCmpRange.aStart.Tab() )
1332cdf0e10cSrcweir 	{
1333cdf0e10cSrcweir 		if ( rRange.aStart.Col() < aCmpRange.aStart.Col() )
1334cdf0e10cSrcweir 			rRange.aStart.SetCol( aCmpRange.aStart.Col() );
1335cdf0e10cSrcweir 		if ( rRange.aStart.Row() < aCmpRange.aStart.Row() )
1336cdf0e10cSrcweir 			rRange.aStart.SetRow( aCmpRange.aStart.Row() );
1337cdf0e10cSrcweir 		if ( rRange.aStart.Tab() < aCmpRange.aStart.Tab() )
1338cdf0e10cSrcweir 			rRange.aStart.SetTab( aCmpRange.aStart.Tab() );
1339cdf0e10cSrcweir 		if ( rRange.aEnd.Col() > aCmpRange.aEnd.Col() )
1340cdf0e10cSrcweir 			rRange.aEnd.SetCol( aCmpRange.aEnd.Col() );
1341cdf0e10cSrcweir 		if ( rRange.aEnd.Row() > aCmpRange.aEnd.Row() )
1342cdf0e10cSrcweir 			rRange.aEnd.SetRow( aCmpRange.aEnd.Row() );
1343cdf0e10cSrcweir 		if ( rRange.aEnd.Tab() > aCmpRange.aEnd.Tab() )
1344cdf0e10cSrcweir 			rRange.aEnd.SetTab( aCmpRange.aEnd.Tab() );
1345cdf0e10cSrcweir 
1346cdf0e10cSrcweir 		return sal_True;
1347cdf0e10cSrcweir 	}
1348cdf0e10cSrcweir 
1349cdf0e10cSrcweir 	return sal_False;		// ausserhalb
1350cdf0e10cSrcweir }
1351cdf0e10cSrcweir 
DoRepaint(const ScRange * pModified)1352cdf0e10cSrcweir void ScConditionalFormat::DoRepaint( const ScRange* pModified )
1353cdf0e10cSrcweir {
1354cdf0e10cSrcweir 	sal_uInt16 i;
1355cdf0e10cSrcweir 	SfxObjectShell* pSh = pDoc->GetDocumentShell();
1356cdf0e10cSrcweir 	if (pSh)
1357cdf0e10cSrcweir 	{
1358cdf0e10cSrcweir 		//	Rahmen/Schatten enthalten?
1359cdf0e10cSrcweir 		//	(alle Bedingungen testen)
1360cdf0e10cSrcweir 		sal_Bool bExtend = sal_False;
1361cdf0e10cSrcweir 		sal_Bool bRotate = sal_False;
1362cdf0e10cSrcweir 		sal_Bool bAttrTested = sal_False;
1363cdf0e10cSrcweir 
1364cdf0e10cSrcweir 		if (!pAreas)		//	RangeList ggf. holen
1365cdf0e10cSrcweir 		{
1366cdf0e10cSrcweir 			pAreas = new ScRangeList;
1367cdf0e10cSrcweir 			pDoc->FindConditionalFormat( nKey, *pAreas );
1368cdf0e10cSrcweir 		}
1369cdf0e10cSrcweir 		sal_uInt16 nCount = (sal_uInt16) pAreas->Count();
1370cdf0e10cSrcweir 		for (i=0; i<nCount; i++)
1371cdf0e10cSrcweir 		{
1372cdf0e10cSrcweir 			ScRange aRange = *pAreas->GetObject(i);
1373cdf0e10cSrcweir 			sal_Bool bDo = sal_True;
1374cdf0e10cSrcweir 			if ( pModified )
1375cdf0e10cSrcweir 			{
1376cdf0e10cSrcweir 				if ( !lcl_CutRange( aRange, *pModified ) )
1377cdf0e10cSrcweir 					bDo = sal_False;
1378cdf0e10cSrcweir 			}
1379cdf0e10cSrcweir 			if (bDo)
1380cdf0e10cSrcweir 			{
1381cdf0e10cSrcweir 			    if ( !bAttrTested )
1382cdf0e10cSrcweir 			    {
1383cdf0e10cSrcweir 			        // #116562# Look at the style's content only if the repaint is necessary
1384cdf0e10cSrcweir 			        // for any condition, to avoid the time-consuming Find() if there are many
1385cdf0e10cSrcweir 			        // conditional formats and styles.
1386cdf0e10cSrcweir             		for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++)
1387cdf0e10cSrcweir             		{
1388cdf0e10cSrcweir             			String aStyle = ppEntries[nEntry]->GetStyle();
1389cdf0e10cSrcweir             			if (aStyle.Len())
1390cdf0e10cSrcweir             			{
1391cdf0e10cSrcweir             				SfxStyleSheetBase* pStyleSheet =
1392cdf0e10cSrcweir             					pDoc->GetStyleSheetPool()->Find( aStyle, SFX_STYLE_FAMILY_PARA );
1393cdf0e10cSrcweir             				if ( pStyleSheet )
1394cdf0e10cSrcweir             				{
1395cdf0e10cSrcweir             					const SfxItemSet& rSet = pStyleSheet->GetItemSet();
1396cdf0e10cSrcweir             					if (rSet.GetItemState( ATTR_BORDER, sal_True ) == SFX_ITEM_SET ||
1397cdf0e10cSrcweir             						rSet.GetItemState( ATTR_SHADOW, sal_True ) == SFX_ITEM_SET)
1398cdf0e10cSrcweir             					{
1399cdf0e10cSrcweir             						bExtend = sal_True;
1400cdf0e10cSrcweir             					}
1401cdf0e10cSrcweir             					if (rSet.GetItemState( ATTR_ROTATE_VALUE, sal_True ) == SFX_ITEM_SET ||
1402cdf0e10cSrcweir             						rSet.GetItemState( ATTR_ROTATE_MODE, sal_True ) == SFX_ITEM_SET)
1403cdf0e10cSrcweir             					{
1404cdf0e10cSrcweir             						bRotate = sal_True;
1405cdf0e10cSrcweir             					}
1406cdf0e10cSrcweir             				}
1407cdf0e10cSrcweir             			}
1408cdf0e10cSrcweir             		}
1409cdf0e10cSrcweir             		bAttrTested = sal_True;
1410cdf0e10cSrcweir 			    }
1411cdf0e10cSrcweir 
1412cdf0e10cSrcweir 				lcl_Extend( aRange, pDoc, bExtend );		// zusammengefasste und bExtend
1413cdf0e10cSrcweir 				if ( bRotate )
1414cdf0e10cSrcweir 				{
1415cdf0e10cSrcweir 					aRange.aStart.SetCol(0);
1416cdf0e10cSrcweir 					aRange.aEnd.SetCol(MAXCOL);		// gedreht: ganze Zeilen
1417cdf0e10cSrcweir 				}
1418cdf0e10cSrcweir 
1419cdf0e10cSrcweir 				// gedreht -> ganze Zeilen
1420cdf0e10cSrcweir 				if ( aRange.aStart.Col() != 0 || aRange.aEnd.Col() != MAXCOL )
1421cdf0e10cSrcweir 				{
1422cdf0e10cSrcweir 					if ( pDoc->HasAttrib( 0,aRange.aStart.Row(),aRange.aStart.Tab(),
1423cdf0e10cSrcweir 											MAXCOL,aRange.aEnd.Row(),aRange.aEnd.Tab(),
1424cdf0e10cSrcweir 											HASATTR_ROTATE ) )
1425cdf0e10cSrcweir 					{
1426cdf0e10cSrcweir 						aRange.aStart.SetCol(0);
1427cdf0e10cSrcweir 						aRange.aEnd.SetCol(MAXCOL);
1428cdf0e10cSrcweir 					}
1429cdf0e10cSrcweir 				}
1430cdf0e10cSrcweir 
1431cdf0e10cSrcweir                 pDoc->RepaintRange( aRange );
1432cdf0e10cSrcweir 			}
1433cdf0e10cSrcweir 		}
1434cdf0e10cSrcweir 	}
1435cdf0e10cSrcweir }
1436cdf0e10cSrcweir 
InvalidateArea()1437cdf0e10cSrcweir void ScConditionalFormat::InvalidateArea()
1438cdf0e10cSrcweir {
1439cdf0e10cSrcweir 	delete pAreas;
1440cdf0e10cSrcweir 	pAreas = NULL;
1441cdf0e10cSrcweir }
1442cdf0e10cSrcweir 
CompileAll()1443cdf0e10cSrcweir void ScConditionalFormat::CompileAll()
1444cdf0e10cSrcweir {
1445cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1446cdf0e10cSrcweir 		ppEntries[i]->CompileAll();
1447cdf0e10cSrcweir }
1448cdf0e10cSrcweir 
CompileXML()1449cdf0e10cSrcweir void ScConditionalFormat::CompileXML()
1450cdf0e10cSrcweir {
1451cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1452cdf0e10cSrcweir 		ppEntries[i]->CompileXML();
1453cdf0e10cSrcweir }
1454cdf0e10cSrcweir 
UpdateReference(UpdateRefMode eUpdateRefMode,const ScRange & rRange,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)1455cdf0e10cSrcweir void ScConditionalFormat::UpdateReference( UpdateRefMode eUpdateRefMode,
1456cdf0e10cSrcweir 								const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
1457cdf0e10cSrcweir {
1458cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1459cdf0e10cSrcweir 		ppEntries[i]->UpdateReference(eUpdateRefMode, rRange, nDx, nDy, nDz);
1460cdf0e10cSrcweir 
1461cdf0e10cSrcweir 	delete pAreas;		// aus dem AttrArray kommt beim Einfuegen/Loeschen kein Aufruf
1462cdf0e10cSrcweir 	pAreas = NULL;
1463cdf0e10cSrcweir }
1464cdf0e10cSrcweir 
RenameCellStyle(const String & rOld,const String & rNew)1465cdf0e10cSrcweir void ScConditionalFormat::RenameCellStyle(const String& rOld, const String& rNew)
1466cdf0e10cSrcweir {
1467cdf0e10cSrcweir     for (sal_uInt16 i=0; i<nEntryCount; i++)
1468cdf0e10cSrcweir         if ( ppEntries[i]->GetStyle() == rOld )
1469cdf0e10cSrcweir             ppEntries[i]->UpdateStyleName( rNew );
1470cdf0e10cSrcweir }
1471cdf0e10cSrcweir 
UpdateMoveTab(SCTAB nOldPos,SCTAB nNewPos)1472cdf0e10cSrcweir void ScConditionalFormat::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
1473cdf0e10cSrcweir {
1474cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1475cdf0e10cSrcweir 		ppEntries[i]->UpdateMoveTab( nOldPos, nNewPos );
1476cdf0e10cSrcweir 
1477cdf0e10cSrcweir 	delete pAreas;		// aus dem AttrArray kommt beim Einfuegen/Loeschen kein Aufruf
1478cdf0e10cSrcweir 	pAreas = NULL;
1479cdf0e10cSrcweir }
1480cdf0e10cSrcweir 
SourceChanged(const ScAddress & rAddr)1481cdf0e10cSrcweir void ScConditionalFormat::SourceChanged( const ScAddress& rAddr )
1482cdf0e10cSrcweir {
1483cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nEntryCount; i++)
1484cdf0e10cSrcweir 		ppEntries[i]->SourceChanged( rAddr );
1485cdf0e10cSrcweir }
1486cdf0e10cSrcweir 
MarkUsedExternalReferences() const1487cdf0e10cSrcweir bool ScConditionalFormat::MarkUsedExternalReferences() const
1488cdf0e10cSrcweir {
1489cdf0e10cSrcweir     bool bAllMarked = false;
1490cdf0e10cSrcweir 	for (sal_uInt16 i=0; !bAllMarked && i<nEntryCount; i++)
1491cdf0e10cSrcweir 		bAllMarked = ppEntries[i]->MarkUsedExternalReferences();
1492cdf0e10cSrcweir     return bAllMarked;
1493cdf0e10cSrcweir }
1494cdf0e10cSrcweir 
1495cdf0e10cSrcweir //------------------------------------------------------------------------
1496cdf0e10cSrcweir 
ScConditionalFormatList(const ScConditionalFormatList & rList)1497cdf0e10cSrcweir ScConditionalFormatList::ScConditionalFormatList(const ScConditionalFormatList& rList) :
1498cdf0e10cSrcweir     ScConditionalFormats_Impl()
1499cdf0e10cSrcweir {
1500cdf0e10cSrcweir 	//	fuer Ref-Undo - echte Kopie mit neuen Tokens!
1501cdf0e10cSrcweir 
1502cdf0e10cSrcweir 	sal_uInt16 nCount = rList.Count();
1503cdf0e10cSrcweir 
1504cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount; i++)
1505cdf0e10cSrcweir 		InsertNew( rList[i]->Clone() );
1506cdf0e10cSrcweir 
1507cdf0e10cSrcweir 	//!		sortierte Eintraege aus rList schneller einfuegen ???
1508cdf0e10cSrcweir }
1509cdf0e10cSrcweir 
ScConditionalFormatList(ScDocument * pNewDoc,const ScConditionalFormatList & rList)1510cdf0e10cSrcweir ScConditionalFormatList::ScConditionalFormatList(ScDocument* pNewDoc,
1511cdf0e10cSrcweir 												const ScConditionalFormatList& rList)
1512cdf0e10cSrcweir {
1513cdf0e10cSrcweir 	//	fuer neues Dokument - echte Kopie mit neuen Tokens!
1514cdf0e10cSrcweir 
1515cdf0e10cSrcweir 	sal_uInt16 nCount = rList.Count();
1516cdf0e10cSrcweir 
1517cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount; i++)
1518cdf0e10cSrcweir 		InsertNew( rList[i]->Clone(pNewDoc) );
1519cdf0e10cSrcweir 
1520cdf0e10cSrcweir 	//!		sortierte Eintraege aus rList schneller einfuegen ???
1521cdf0e10cSrcweir }
1522cdf0e10cSrcweir 
operator ==(const ScConditionalFormatList & r) const1523cdf0e10cSrcweir sal_Bool ScConditionalFormatList::operator==( const ScConditionalFormatList& r ) const
1524cdf0e10cSrcweir {
1525cdf0e10cSrcweir 	// fuer Ref-Undo - interne Variablen werden nicht verglichen
1526cdf0e10cSrcweir 
1527cdf0e10cSrcweir 	sal_uInt16 nCount = Count();
1528cdf0e10cSrcweir 	sal_Bool bEqual = ( nCount == r.Count() );
1529cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount && bEqual; i++)			// Eintraege sind sortiert
1530cdf0e10cSrcweir 		if ( !(*this)[i]->EqualEntries(*r[i]) )			// Eintraege unterschiedlich ?
1531cdf0e10cSrcweir 			bEqual = sal_False;
1532cdf0e10cSrcweir 
1533cdf0e10cSrcweir 	return bEqual;
1534cdf0e10cSrcweir }
1535cdf0e10cSrcweir 
GetFormat(sal_uInt32 nKey)1536cdf0e10cSrcweir ScConditionalFormat* ScConditionalFormatList::GetFormat( sal_uInt32 nKey )
1537cdf0e10cSrcweir {
1538cdf0e10cSrcweir 	//!	binaer suchen
1539cdf0e10cSrcweir 
1540cdf0e10cSrcweir 	sal_uInt16 nCount = Count();
1541cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount; i++)
1542cdf0e10cSrcweir 		if ((*this)[i]->GetKey() == nKey)
1543cdf0e10cSrcweir 			return (*this)[i];
1544cdf0e10cSrcweir 
1545cdf0e10cSrcweir 	DBG_ERROR("ScConditionalFormatList: Eintrag nicht gefunden");
1546cdf0e10cSrcweir 	return NULL;
1547cdf0e10cSrcweir }
1548cdf0e10cSrcweir 
CompileAll()1549cdf0e10cSrcweir void ScConditionalFormatList::CompileAll()
1550cdf0e10cSrcweir {
1551cdf0e10cSrcweir 	sal_uInt16 nCount = Count();
1552cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount; i++)
1553cdf0e10cSrcweir 		(*this)[i]->CompileAll();
1554cdf0e10cSrcweir }
1555cdf0e10cSrcweir 
CompileXML()1556cdf0e10cSrcweir void ScConditionalFormatList::CompileXML()
1557cdf0e10cSrcweir {
1558cdf0e10cSrcweir 	sal_uInt16 nCount = Count();
1559cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount; i++)
1560cdf0e10cSrcweir 		(*this)[i]->CompileXML();
1561cdf0e10cSrcweir }
1562cdf0e10cSrcweir 
UpdateReference(UpdateRefMode eUpdateRefMode,const ScRange & rRange,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)1563cdf0e10cSrcweir void ScConditionalFormatList::UpdateReference( UpdateRefMode eUpdateRefMode,
1564cdf0e10cSrcweir 								const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
1565cdf0e10cSrcweir {
1566cdf0e10cSrcweir 	sal_uInt16 nCount = Count();
1567cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount; i++)
1568cdf0e10cSrcweir 		(*this)[i]->UpdateReference( eUpdateRefMode, rRange, nDx, nDy, nDz );
1569cdf0e10cSrcweir }
1570cdf0e10cSrcweir 
RenameCellStyle(const String & rOld,const String & rNew)1571cdf0e10cSrcweir void ScConditionalFormatList::RenameCellStyle( const String& rOld, const String& rNew )
1572cdf0e10cSrcweir {
1573cdf0e10cSrcweir     sal_uLong nCount=Count();
1574cdf0e10cSrcweir     for (sal_uInt16 i=0; i<nCount; i++)
1575cdf0e10cSrcweir         (*this)[i]->RenameCellStyle(rOld,rNew);
1576cdf0e10cSrcweir }
1577cdf0e10cSrcweir 
UpdateMoveTab(SCTAB nOldPos,SCTAB nNewPos)1578cdf0e10cSrcweir void ScConditionalFormatList::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos )
1579cdf0e10cSrcweir {
1580cdf0e10cSrcweir 	sal_uInt16 nCount = Count();
1581cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount; i++)
1582cdf0e10cSrcweir 		(*this)[i]->UpdateMoveTab( nOldPos, nNewPos );
1583cdf0e10cSrcweir }
1584cdf0e10cSrcweir 
SourceChanged(const ScAddress & rAddr)1585cdf0e10cSrcweir void ScConditionalFormatList::SourceChanged( const ScAddress& rAddr )
1586cdf0e10cSrcweir {
1587cdf0e10cSrcweir 	sal_uInt16 nCount = Count();
1588cdf0e10cSrcweir 	for (sal_uInt16 i=0; i<nCount; i++)
1589cdf0e10cSrcweir 		(*this)[i]->SourceChanged( rAddr );
1590cdf0e10cSrcweir }
1591cdf0e10cSrcweir 
MarkUsedExternalReferences() const1592cdf0e10cSrcweir bool ScConditionalFormatList::MarkUsedExternalReferences() const
1593cdf0e10cSrcweir {
1594cdf0e10cSrcweir     bool bAllMarked = false;
1595cdf0e10cSrcweir 	sal_uInt16 nCount = Count();
1596cdf0e10cSrcweir 	for (sal_uInt16 i=0; !bAllMarked && i<nCount; i++)
1597cdf0e10cSrcweir 		bAllMarked = (*this)[i]->MarkUsedExternalReferences();
1598cdf0e10cSrcweir     return bAllMarked;
1599cdf0e10cSrcweir }
1600