xref: /aoo41x/main/sc/source/core/data/table4.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2011 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 // System - Includes -----------------------------------------------------
32 
33 
34 
35 #ifdef _MSC_VER
36 #pragma optimize("",off)
37 										// sonst Absturz Win beim Fuellen
38 #endif
39 
40 // INCLUDE ---------------------------------------------------------------
41 
42 #include "scitems.hxx"
43 #include <svx/algitem.hxx>
44 #include <editeng/boxitem.hxx>
45 #include <editeng/brshitem.hxx>
46 #include <editeng/cntritem.hxx>
47 #include <editeng/colritem.hxx>
48 #include <editeng/crsditem.hxx>
49 #include <editeng/fhgtitem.hxx>
50 #include <editeng/fontitem.hxx>
51 #include <editeng/langitem.hxx>
52 #include <editeng/postitem.hxx>
53 #include <editeng/shdditem.hxx>
54 #include <editeng/udlnitem.hxx>
55 #include <editeng/wghtitem.hxx>
56 #include <svx/rotmodit.hxx>
57 #include <editeng/editobj.hxx>
58 #include <editeng/editeng.hxx>
59 #include <editeng/eeitem.hxx>
60 #include <editeng/escpitem.hxx>
61 #include <svl/zforlist.hxx>
62 #include <vcl/keycodes.hxx>
63 #include <rtl/math.hxx>
64 #include <unotools/charclass.hxx>
65 
66 #include "attrib.hxx"
67 #include "patattr.hxx"
68 #include "cell.hxx"
69 #include "table.hxx"
70 #include "globstr.hrc"
71 #include "global.hxx"
72 #include "document.hxx"
73 #include "autoform.hxx"
74 #include "userlist.hxx"
75 #include "zforauto.hxx"
76 #include "subtotal.hxx"
77 #include "formula/errorcodes.hxx"
78 #include "rangenam.hxx"
79 #include "docpool.hxx"
80 #include "progress.hxx"
81 #include "segmenttree.hxx"
82 
83 #include <math.h>
84 
85 // STATIC DATA -----------------------------------------------------------
86 
87 #define _D_MAX_LONG_  (double) 0x7fffffff
88 
89 extern sal_uInt16 nScFillModeMouseModifier;		// global.cxx
90 
91 // -----------------------------------------------------------------------
92 
93 short lcl_DecompValueString( String& aValue, sal_Int32& nVal, sal_uInt16* pMinDigits = NULL )
94 {
95 	if ( !aValue.Len() )
96 	{
97 		nVal = 0;
98 		return 0;
99 	}
100 	const sal_Unicode* p = aValue.GetBuffer();
101 	xub_StrLen nNeg = 0;
102 	xub_StrLen nNum = 0;
103 	if ( p[nNum] == '-' )
104 		nNum = nNeg = 1;
105 	while ( p[nNum] && CharClass::isAsciiNumeric( p[nNum] ) )
106 		nNum++;
107 
108     sal_Unicode cNext = p[nNum];            // 0 if at the end
109     sal_Unicode cLast = p[aValue.Len()-1];
110 
111     // #i5550# If there are numbers at the beginning and the end,
112     // prefer the one at the beginning only if it's followed by a space.
113     // Otherwise, use the number at the end, to enable things like IP addresses.
114     if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(cLast) ) )
115 	{	// number at the beginning
116 		nVal = aValue.Copy( 0, nNum ).ToInt32();
117 		//	#60893# any number with a leading zero sets the minimum number of digits
118 		if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) )
119 			*pMinDigits = nNum - nNeg;
120 		aValue.Erase( 0, nNum );
121 		return -1;
122 	}
123 	else
124 	{
125 		nNeg = 0;
126 		xub_StrLen nEnd = nNum = aValue.Len() - 1;
127 		while ( nNum && CharClass::isAsciiNumeric( p[nNum] ) )
128 			nNum--;
129 		if ( p[nNum] == '-' )
130 		{
131 			nNum--;
132 			nNeg = 1;
133 		}
134 		if ( nNum < nEnd - nNeg )
135 		{	// number at the end
136 			nVal = aValue.Copy( nNum + 1 ).ToInt32();
137 			//	#60893# any number with a leading zero sets the minimum number of digits
138 			if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) )
139 				*pMinDigits = nEnd - nNum - nNeg;
140 			aValue.Erase( nNum + 1 );
141 			return 1;
142 		}
143 	}
144 	nVal = 0;
145 	return 0;
146 }
147 
148 String lcl_ValueString( sal_Int32 nValue, sal_uInt16 nMinDigits )
149 {
150 	if ( nMinDigits <= 1 )
151 		return String::CreateFromInt32( nValue );			// simple case...
152 	else
153 	{
154 		String aStr = String::CreateFromInt32( Abs( nValue ) );
155 		if ( aStr.Len() < nMinDigits )
156 		{
157 			String aZero;
158 			aZero.Fill( nMinDigits - aStr.Len(), '0' );
159 			aStr.Insert( aZero, 0 );
160 		}
161 		//	nMinDigits doesn't include the '-' sign -> add after inserting zeros
162 		if ( nValue < 0 )
163 			aStr.Insert( '-', 0 );
164 		return aStr;
165 	}
166 }
167 
168 static ScBaseCell * lcl_getSuffixCell( ScDocument* pDocument, sal_Int32 nValue,
169         sal_uInt16 nDigits, const String& rSuffix, CellType eCellType,
170         sal_Bool bIsOrdinalSuffix )
171 {
172     String aValue( lcl_ValueString( nValue, nDigits ));
173     if (!bIsOrdinalSuffix)
174         return new ScStringCell( aValue += rSuffix);
175 
176     String aOrdinalSuffix( ScGlobal::GetOrdinalSuffix( nValue));
177     if (eCellType != CELLTYPE_EDIT)
178         return new ScStringCell( aValue += aOrdinalSuffix);
179 
180     EditEngine aEngine( pDocument->GetEnginePool() );
181     SfxItemSet aAttr = aEngine.GetEmptyItemSet();
182     aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT));
183     aEngine.SetText( aValue );
184     aEngine.QuickInsertText( aOrdinalSuffix, ESelection( 0, aValue.Len(), 0,
185                 aValue.Len() + aOrdinalSuffix.Len()));
186     aEngine.QuickSetAttribs( aAttr, ESelection( 0, aValue.Len(), 0, aValue.Len() +
187                 aOrdinalSuffix.Len()));
188     return new ScEditCell( aEngine.CreateTextObject(), pDocument, NULL );
189 }
190 
191 void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
192 							FillCmd& rCmd, FillDateCmd& rDateCmd,
193 							double& rInc, sal_uInt16& rMinDigits,
194 							ScUserListData*& rListData, sal_uInt16& rListIndex)
195 {
196 	DBG_ASSERT( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: falscher Bereich" );
197 
198 	rInc = 0.0;
199 	rMinDigits = 0;
200 	rListData = NULL;
201 	rCmd = FILL_SIMPLE;
202 	if (( nScFillModeMouseModifier & KEY_MOD1 )||IsDataFiltered())	//i89232
203 		return ;		// Ctrl-Taste: Copy
204 
205 	SCCOL nAddX;
206 	SCROW nAddY;
207 	SCSIZE nCount;
208 	if (nCol1 == nCol2)
209 	{
210 		nAddX = 0;
211 		nAddY = 1;
212 		nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
213 	}
214 	else
215 	{
216 		nAddX = 1;
217 		nAddY = 0;
218 		nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
219 	}
220 
221 	SCCOL nCol = nCol1;
222 	SCROW nRow = nRow1;
223 
224 	ScBaseCell* pFirstCell = GetCell( nCol, nRow );
225 	CellType eCellType = pFirstCell ? pFirstCell->GetCellType() : CELLTYPE_NONE;
226 
227 	if (eCellType == CELLTYPE_VALUE)
228 	{
229 		sal_uInt32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
230 		sal_Bool bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE );
231 		if (bDate)
232 		{
233 			if (nCount > 1)
234 			{
235 				long nCmpInc = 0;
236 				double nVal;
237 				Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
238 				Date aDate1 = aNullDate;
239 				nVal = ((ScValueCell*)pFirstCell)->GetValue();
240 				aDate1 += (long)nVal;
241 				Date aDate2 = aNullDate;
242 				nVal = GetValue(nCol+nAddX, nRow+nAddY);
243 				aDate2 += (long)nVal;
244 				if ( aDate1 != aDate2 )
245 				{
246 					FillDateCmd eType;
247 					long nDDiff = aDate2.GetDay()   - (long) aDate1.GetDay();
248 					long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
249 					long nYDiff = aDate2.GetYear()  - (long) aDate1.GetYear();
250 					if ( nDDiff )
251 					{
252 						eType = FILL_DAY;
253 						nCmpInc = aDate2 - aDate1;
254 					}
255 					else
256 					{
257 						eType = FILL_MONTH;
258 						nCmpInc = nMDiff + 12 * nYDiff;
259 					}
260 
261                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
262                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
263 					sal_Bool bVal = sal_True;
264 					for (sal_uInt16 i=1; i<nCount && bVal; i++)
265 					{
266 						ScBaseCell* pCell = GetCell(nCol,nRow);
267 						if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
268 						{
269 							nVal = ((ScValueCell*)pCell)->GetValue();
270 							aDate2 = aNullDate + (long) nVal;
271 							if ( eType == FILL_DAY )
272 							{
273 								if ( aDate2-aDate1 != nCmpInc )
274 									bVal = sal_False;
275 							}
276 							else
277 							{
278 								nDDiff = aDate2.GetDay()   - (long) aDate1.GetDay();
279 								nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
280 								nYDiff = aDate2.GetYear()  - (long) aDate1.GetYear();
281 								if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
282 									bVal = sal_False;
283 							}
284 							aDate1 = aDate2;
285                             nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
286                             nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
287 						}
288 						else
289 							bVal = sal_False;	// #50965# kein Datum passt auch nicht
290 					}
291 					if (bVal)
292 					{
293 						if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
294 						{
295 							eType = FILL_YEAR;
296 							nCmpInc /= 12;
297 						}
298 						rCmd = FILL_DATE;
299 						rDateCmd = eType;
300 						rInc = nCmpInc;
301 					}
302 				}
303 			}
304 			else							// einzelnes Datum -> Tage hochzaehlen
305 			{
306 				rCmd = FILL_DATE;
307 				rDateCmd = FILL_DAY;
308 				rInc = 1.0;
309 			}
310 		}
311 		else
312 		{
313 			if (nCount > 1)
314 			{
315 				double nVal1 = ((ScValueCell*)pFirstCell)->GetValue();
316 				double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
317 				rInc = nVal2 - nVal1;
318                 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
319                 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
320 				sal_Bool bVal = sal_True;
321 				for (sal_uInt16 i=1; i<nCount && bVal; i++)
322 				{
323 					ScBaseCell* pCell = GetCell(nCol,nRow);
324 					if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
325 					{
326 						nVal2 = ((ScValueCell*)pCell)->GetValue();
327 						double nDiff = nVal2 - nVal1;
328 						if ( !::rtl::math::approxEqual( nDiff, rInc ) )
329 							bVal = sal_False;
330 						nVal1 = nVal2;
331 					}
332 					else
333 						bVal = sal_False;
334                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
335                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
336 				}
337 				if (bVal)
338 					rCmd = FILL_LINEAR;
339 			}
340 		}
341 	}
342 	else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
343 	{
344 		String aStr;
345 		GetString(nCol, nRow, aStr);
346 		rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr));
347 		if (rListData)
348 		{
349 			rListData->GetSubIndex(aStr, rListIndex);
350             nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
351             nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
352 			for (sal_uInt16 i=1; i<nCount && rListData; i++)
353 			{
354 				GetString(nCol, nRow, aStr);
355 				if (!rListData->GetSubIndex(aStr, rListIndex))
356 					rListData = NULL;
357                 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
358                 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
359 			}
360 		}
361 		else if ( nCount > 1 )
362 		{
363 			//	pass rMinDigits to all DecompValueString calls
364 			//	-> longest number defines rMinDigits
365 
366 			sal_Int32 nVal1;
367 			short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
368 			if ( nFlag1 )
369 			{
370 				sal_Int32 nVal2;
371 				GetString( nCol+nAddX, nRow+nAddY, aStr );
372 				short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
373 				if ( nFlag1 == nFlag2 )
374 				{
375 					rInc = (double)nVal2 - (double)nVal1;
376                     nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
377                     nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
378 					sal_Bool bVal = sal_True;
379 					for (sal_uInt16 i=1; i<nCount && bVal; i++)
380 					{
381 						ScBaseCell* pCell = GetCell(nCol,nRow);
382                         CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE;
383                         if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
384 						{
385 							if ( eType == CELLTYPE_STRING )
386 								((ScStringCell*)pCell)->GetString( aStr );
387 							else
388 								((ScEditCell*)pCell)->GetString( aStr );
389 							nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
390 							if ( nFlag1 == nFlag2 )
391 							{
392 								double nDiff = (double)nVal2 - (double)nVal1;
393 								if ( !::rtl::math::approxEqual( nDiff, rInc ) )
394 									bVal = sal_False;
395 								nVal1 = nVal2;
396 							}
397 							else
398 								bVal = sal_False;
399 						}
400 						else
401 							bVal = sal_False;
402                         nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
403                         nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
404 					}
405 					if (bVal)
406 						rCmd = FILL_LINEAR;
407 				}
408 			}
409 		}
410 		else
411 		{
412 			//	call DecompValueString to set rMinDigits
413 			sal_Int32 nDummy;
414 			lcl_DecompValueString( aStr, nDummy, &rMinDigits );
415 		}
416 	}
417 }
418 
419 void ScTable::FillFormula(sal_uLong& /* nFormulaCounter */, sal_Bool /* bFirst */, ScFormulaCell* pSrcCell,
420 						  SCCOL nDestCol, SCROW nDestRow, sal_Bool bLast )
421 {
422 /*	sal_uInt16 nTokArrLen = pSrcCell->GetTokenArrayLen();
423 	if ( nTokArrLen > 15 )							// mehr als =A1 oder =67
424 	{
425 		ScRangeName* pRangeName = pDocument->GetRangeName();
426 		String aName("___SC_");						// Wird dieser String veraendert,
427 													// auch in document2 EraseNonUsed...
428 													// mitaendern!!
429 		aName += pRangeName->GetSharedMaxIndex() + 1;
430 		aName += '_';
431 		aName += nFormulaCounter;
432 		nFormulaCounter++;
433 		if (bFirst)
434 		{
435 			ScRangeData *pAktRange = new ScRangeData(
436 							pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen,
437 							pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED);
438 			if (!pRangeName->Insert( pAktRange ))
439 				delete pAktRange;
440 			else
441 				bSharedNameInserted = sal_True;
442 		}
443 		sal_uInt16 nIndex;
444 		pRangeName->SearchName(aName, nIndex);
445 		if (!pRangeName)
446 		{
447 			DBG_ERROR("ScTable::FillFormula: Falscher Name");
448 			return;
449 		}
450 		nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex();
451 		ScTokenArray aArr;
452 		aArr.AddName(nIndex);
453 		aArr.AddOpCode(ocStop);
454 		ScFormulaCell* pDestCell = new ScFormulaCell
455 			(pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr );
456 		aCol[nDestCol].Insert(nDestRow, pDestCell);
457 	}
458 	else
459 */	{
460 		pDocument->SetNoListening( sal_True );	// noch falsche Referenzen
461         ScAddress aAddr( nDestCol, nDestRow, nTab );
462         ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr );
463 		aCol[nDestCol].Insert(nDestRow, pDestCell);
464 #if 0
465 // mit RelRefs unnoetig
466 		pDestCell->UpdateReference(URM_COPY,
467 						 ScRange( aAddr, aAddr ),
468 						 nDestCol - pSrcCell->aPos.Col(),
469 						 nDestRow - pSrcCell->aPos.Row(), 0);
470 #endif
471 		if ( bLast && pDestCell->GetMatrixFlag() )
472 		{
473 			ScAddress aOrg;
474 			if ( pDestCell->GetMatrixOrigin( aOrg ) )
475 			{
476 				if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
477 				{
478 					ScBaseCell* pOrgCell = pDocument->GetCell( aOrg );
479 					if ( pOrgCell && pOrgCell->GetCellType() == CELLTYPE_FORMULA
480 					  && ((ScFormulaCell*)pOrgCell)->GetMatrixFlag() == MM_FORMULA )
481 					{
482 						((ScFormulaCell*)pOrgCell)->SetMatColsRows(
483 							nDestCol - aOrg.Col() + 1,
484 							nDestRow - aOrg.Row() + 1 );
485 					}
486 					else
487 					{
488 						DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" );
489 					}
490 				}
491 				else
492 				{
493 					DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" );
494 				}
495 			}
496 			else
497 			{
498 				DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" );
499 			}
500 		}
501 		pDocument->SetNoListening( sal_False );
502 		pDestCell->StartListeningTo( pDocument );
503 	}
504 }
505 
506 void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
507 						sal_uLong nFillCount, FillDir eFillDir, ScProgress& rProgress )
508 {
509 	if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
510 		return;
511 
512 	//
513 	//	Richtung auswerten
514 	//
515 
516 	sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
517 	sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
518 
519     sal_uLong nCol = 0;
520     sal_uLong nRow = 0;
521 	sal_uLong& rInner = bVertical ? nRow : nCol;		// Schleifenvariablen
522 	sal_uLong& rOuter = bVertical ? nCol : nRow;
523 	sal_uLong nOStart;
524 	sal_uLong nOEnd;
525 	sal_uLong nIStart;
526 	sal_uLong nIEnd;
527 	sal_uLong nISrcStart;
528 	sal_uLong nISrcEnd;
529 
530 	if (bVertical)
531 	{
532 		nOStart = nCol1;
533 		nOEnd = nCol2;
534 		if (bPositive)
535 		{
536 			nISrcStart = nRow1;
537 			nISrcEnd = nRow2;
538 			nIStart = nRow2 + 1;
539 			nIEnd = nRow2 + nFillCount;
540 		}
541 		else
542 		{
543 			nISrcStart = nRow2;
544 			nISrcEnd = nRow1;
545 			nIStart = nRow1 - 1;
546 			nIEnd = nRow1 - nFillCount;
547 		}
548 	}
549 	else
550 	{
551 		nOStart = nRow1;
552 		nOEnd = nRow2;
553 		if (bPositive)
554 		{
555 			nISrcStart = nCol1;
556 			nISrcEnd = nCol2;
557 			nIStart = nCol2 + 1;
558 			nIEnd = nCol2 + nFillCount;
559 		}
560 		else
561 		{
562 			nISrcStart = nCol2;
563 			nISrcEnd = nCol1;
564 			nIStart = nCol1 - 1;
565 			nIEnd = nCol1 - nFillCount;
566 		}
567 	}
568 	sal_uLong nIMin = nIStart;
569 	sal_uLong nIMax = nIEnd;
570 	PutInOrder(nIMin,nIMax);
571     sal_Bool bHasFiltered = IsDataFiltered();
572     if (!bHasFiltered)  //modify for i89232
573 	{
574 		if (bVertical)
575 			DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
576 		else
577 			DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
578 	}
579 	sal_uLong nProgress = rProgress.GetState();
580 
581 	//
582 	//	ausfuehren
583 	//
584 
585 	sal_uLong nActFormCnt = 0;
586 	for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
587 	{
588 		sal_uLong nMaxFormCnt = 0;						// fuer Formeln
589 
590 		//	Attributierung uebertragen
591 
592         const ScPatternAttr* pSrcPattern = NULL;
593         const ScStyleSheet* pStyleSheet = NULL;
594 		sal_uLong nAtSrc = nISrcStart;
595 		ScPatternAttr* pNewPattern = NULL;
596 		sal_Bool bGetPattern = sal_True;
597         rInner = nIStart;
598         while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
599 		{
600 			if ( bGetPattern )
601 			{
602 				if ( pNewPattern )
603 					delete pNewPattern;
604 				if (bVertical)		// rInner&:=nRow, rOuter&:=nCol
605 					pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc));
606 				else                // rInner&:=nCol, rOuter&:=nRow
607 					pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow));
608 				bGetPattern = sal_False;
609 				pStyleSheet = pSrcPattern->GetStyleSheet();
610 				//	Merge/Mergeflag nicht uebernehmen,
611 				const SfxItemSet& rSet = pSrcPattern->GetItemSet();
612 				if ( rSet.GetItemState(ATTR_MERGE, sal_False) == SFX_ITEM_SET
613 				  || rSet.GetItemState(ATTR_MERGE_FLAG, sal_False) == SFX_ITEM_SET )
614 				{
615 					pNewPattern = new ScPatternAttr( *pSrcPattern );
616 					SfxItemSet& rNewSet = pNewPattern->GetItemSet();
617 					rNewSet.ClearItem(ATTR_MERGE);
618 					rNewSet.ClearItem(ATTR_MERGE_FLAG);
619 				}
620 				else
621 					pNewPattern = NULL;
622 			}
623 
624             if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered )
625 			{
626 				//	Attribute komplett am Stueck setzen
627 				if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
628 				{
629 					//	Default steht schon da (DeleteArea)
630 					SCROW nY1 = static_cast<SCROW>(Min( nIStart, nIEnd ));
631 					SCROW nY2 = static_cast<SCROW>(Max( nIStart, nIEnd ));
632 					if ( pStyleSheet )
633 						aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
634 					if ( pNewPattern )
635 						aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
636 					else
637 						aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
638 				}
639 				break;		// Schleife abbrechen
640 			}
641 
642             if ( !RowFiltered(nRow) )
643             {
644                 if ( bHasFiltered )
645                     DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow),
646                                static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL);
647 
648                 if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
649                 {
650                     //  Vorlage auch uebernehmen
651                     //! am AttrArray mit ApplyPattern zusammenfassen ??
652                     if ( pStyleSheet )
653                         aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
654 
655                     //  ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
656                     if ( pNewPattern )
657                         aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
658                     else
659                         aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
660                 }
661 
662                 if (nAtSrc==nISrcEnd)
663                 {
664                     if ( nAtSrc != nISrcStart )
665                     {   // mehr als eine Source-Zelle
666                         nAtSrc = nISrcStart;
667                         bGetPattern = sal_True;
668                     }
669                 }
670                 else if (bPositive)
671                 {
672                     ++nAtSrc;
673                     bGetPattern = sal_True;
674                 }
675                 else
676                 {
677                     --nAtSrc;
678                     bGetPattern = sal_True;
679                 }
680             }
681 
682 			if (rInner == nIEnd) break;
683 			if (bPositive) ++rInner; else --rInner;
684 		}
685 		if ( pNewPattern )
686 			delete pNewPattern;
687 
688 		//	Analyse
689 
690 		FillCmd eFillCmd;
691 		FillDateCmd eDateCmd;
692 		double nInc;
693 		sal_uInt16 nMinDigits;
694 		ScUserListData* pListData = NULL;
695 		sal_uInt16 nListIndex;
696 		if (bVertical)
697             FillAnalyse(static_cast<SCCOL>(nCol),nRow1,
698                     static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd,
699                     nInc,nMinDigits, pListData,nListIndex);
700 		else
701             FillAnalyse(nCol1,static_cast<SCROW>(nRow),
702                     nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd,
703                     nInc,nMinDigits, pListData,nListIndex);
704 
705 		if (bVertical)
706 			aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
707 
708 		if (pListData)
709 		{
710 			sal_uInt16 nListCount = pListData->GetSubCount();
711 			if ( !bPositive )
712 			{
713 				//	nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen
714 				sal_uLong nSub = nISrcStart - nISrcEnd;
715 				for (sal_uLong i=0; i<nSub; i++)
716 				{
717 					if (nListIndex == 0) nListIndex = nListCount;
718 					--nListIndex;
719 				}
720 			}
721 
722             rInner = nIStart;
723             while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
724 			{
725 				if (bPositive)
726 				{
727 					++nListIndex;
728 					if (nListIndex >= nListCount) nListIndex = 0;
729 				}
730 				else
731 				{
732 					if (nListIndex == 0) nListIndex = nListCount;
733 					--nListIndex;
734 				}
735 				aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScStringCell(pListData->GetSubStr(nListIndex)));
736 
737 				if (rInner == nIEnd) break;
738 				if (bPositive) ++rInner; else --rInner;
739 			}
740 			nProgress += nIMax - nIMin + 1;
741 			rProgress.SetStateOnPercent( nProgress );
742 		}
743 		else if (eFillCmd == FILL_SIMPLE)			// Auffuellen mit Muster
744 		{
745 			sal_uLong nSource = nISrcStart;
746 			double nDelta;
747             if (( nScFillModeMouseModifier & KEY_MOD1 )||bHasFiltered) //i89232
748 				nDelta = 0.0;
749 			else if ( bPositive )
750 				nDelta = 1.0;
751 			else
752 				nDelta = -1.0;
753             double nVal = 0.0;
754 			sal_uLong nFormulaCounter = nActFormCnt;
755 			sal_Bool bFirst = sal_True;
756 			sal_Bool bGetCell = sal_True;
757 			sal_uInt16 nCellDigits = 0;
758 			short nHeadNoneTail = 0;
759 			sal_Int32 nStringValue = 0;
760 			String aValue;
761             ScBaseCell* pSrcCell = NULL;
762             CellType eCellType = CELLTYPE_NONE;
763             sal_Bool bIsOrdinalSuffix = sal_False;
764 			sal_Bool bRowFiltered = sal_False; //i89232
765 
766             rInner = nIStart;
767             while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
768 			{
769 				if ( bGetCell )
770 				{
771 					if (bVertical)		// rInner&:=nRow, rOuter&:=nCol
772 						pSrcCell = aCol[nCol].GetCell( static_cast<SCROW>(nSource) );
773 					else				// rInner&:=nCol, rOuter&:=nRow
774 						pSrcCell = aCol[nSource].GetCell( static_cast<SCROW>(nRow) );
775 					bGetCell = sal_False;
776 					if ( pSrcCell )
777 					{
778 						eCellType = pSrcCell->GetCellType();
779 						switch ( eCellType )
780 						{
781 							case CELLTYPE_VALUE:
782 								nVal = ((ScValueCell*)pSrcCell)->GetValue();
783 							break;
784 							case CELLTYPE_STRING:
785 							case CELLTYPE_EDIT:
786 								if ( eCellType == CELLTYPE_STRING )
787 									((ScStringCell*)pSrcCell)->GetString( aValue );
788 								else
789 									((ScEditCell*)pSrcCell)->GetString( aValue );
790                                 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered)   //i89232
791 								{
792 									nCellDigits = 0;	// look at each source cell individually
793 									nHeadNoneTail = lcl_DecompValueString(
794 										aValue, nStringValue, &nCellDigits );
795 
796                                     bIsOrdinalSuffix = aValue.Equals(
797                                             ScGlobal::GetOrdinalSuffix( nStringValue));
798 								}
799 							break;
800                             default:
801                             {
802                                 // added to avoid warnings
803                             }
804 						}
805 					}
806 					else
807 						eCellType = CELLTYPE_NONE;
808 				}
809 
810 				//Modify for i89232
811 				bRowFiltered = mpFilteredRows->getValue(nRow);
812 
813 				if (!bRowFiltered)
814 				{
815 				//End of i89232
816 
817                     switch (eCellType)
818                     {
819                         case CELLTYPE_VALUE:
820                             aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta));
821                             break;
822                         case CELLTYPE_STRING:
823                         case CELLTYPE_EDIT:
824                             if ( nHeadNoneTail )
825                             {
826                                 // #i48009# with the "nStringValue+(long)nDelta" expression within the
827                                 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
828                                 // so nNextValue is now calculated ahead.
829                                 sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
830 
831                                 String aStr;
832                                 if ( nHeadNoneTail < 0 )
833                                 {
834                                     aCol[nCol].Insert( static_cast<SCROW>(nRow),
835                                             lcl_getSuffixCell( pDocument,
836                                                 nNextValue, nCellDigits, aValue,
837                                                 eCellType, bIsOrdinalSuffix));
838                                 }
839                                 else
840                                 {
841                                     aStr = aValue;
842                                     aStr += lcl_ValueString( nNextValue, nCellDigits );
843                                     aCol[nCol].Insert( static_cast<SCROW>(nRow),
844                                             new ScStringCell( aStr));
845                                 }
846                             }
847                             else
848                             {
849                                 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
850                                 switch ( eCellType )
851                                 {
852                                     case CELLTYPE_STRING:
853                                     case CELLTYPE_EDIT:
854                                         aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
855                                     break;
856                                     default:
857                                     {
858                                         // added to avoid warnings
859                                     }
860                                 }
861                             }
862                             break;
863                         case CELLTYPE_FORMULA :
864                             FillFormula( nFormulaCounter, bFirst,
865                                     (ScFormulaCell*) pSrcCell,
866                                     static_cast<SCCOL>(nCol),
867                                     static_cast<SCROW>(nRow), (rInner == nIEnd) );
868                             if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
869                                 nMaxFormCnt = nFormulaCounter - nActFormCnt;
870                             break;
871                         default:
872                         {
873                             // added to avoid warnings
874                         }
875                     }
876 
877                     if (nSource==nISrcEnd)
878                     {
879                         if ( nSource != nISrcStart )
880                         {   // mehr als eine Source-Zelle
881                             nSource = nISrcStart;
882                             bGetCell = sal_True;
883                         }
884                         if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered ) //i89232
885                         {
886                             if ( bPositive )
887                                 nDelta += 1.0;
888                             else
889                                 nDelta -= 1.0;
890                         }
891                         nFormulaCounter = nActFormCnt;
892                         bFirst = sal_False;
893                     }
894                     else if (bPositive)
895                     {
896                         ++nSource;
897                         bGetCell = sal_True;
898                     }
899                     else
900                     {
901                         --nSource;
902                         bGetCell = sal_True;
903 					}
904 				}
905 
906 				//	Progress in der inneren Schleife nur bei teuren Zellen,
907 				//	und auch dann nicht fuer jede einzelne
908 
909 				++nProgress;
910 				if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT )
911 					rProgress.SetStateOnPercent( nProgress );
912 
913 				if (rInner == nIEnd) break;
914 				if (bPositive) ++rInner; else --rInner;
915 			}
916 			rProgress.SetStateOnPercent( nProgress );
917 		}
918 		else
919 		{
920 			if (!bPositive)
921 				nInc = -nInc;
922 			double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
923 			if (bVertical)
924                 FillSeries( static_cast<SCCOL>(nCol), nRow1,
925                         static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir,
926                         eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False,
927                         rProgress );
928 			else
929                 FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2,
930                         static_cast<SCROW>(nRow), nFillCount, eFillDir,
931                         eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False,
932                         rProgress );
933 			nProgress = rProgress.GetState();
934 		}
935 
936 		nActFormCnt += nMaxFormCnt;
937 	}
938 }
939 
940 String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
941 {
942 	String aValue;
943 
944 	SCCOL nCol1 = rSource.aStart.Col();
945 	SCROW nRow1 = rSource.aStart.Row();
946 	SCCOL nCol2 = rSource.aEnd.Col();
947 	SCROW nRow2 = rSource.aEnd.Row();
948 	sal_Bool bOk = sal_True;
949     long nIndex = 0;
950     sal_uLong nSrcCount = 0;
951     FillDir eFillDir = FILL_TO_BOTTOM;
952 	if ( nEndX == nCol2 && nEndY == nRow2 )		// leer
953 		bOk = sal_False;
954 	else if ( nEndX == nCol2 )					// nach oben/unten
955 	{
956 		nEndX = nCol2 = nCol1;					// nur erste Spalte ansehen
957 		nSrcCount = nRow2 - nRow1 + 1;
958 		nIndex = ((long)nEndY) - nRow1;			// kann negativ werden
959 		if ( nEndY >= nRow1 )
960 			eFillDir = FILL_TO_BOTTOM;
961 		else
962 			eFillDir = FILL_TO_TOP;
963 	}
964 	else if ( nEndY == nRow2 )					// nach links/rechts
965 	{
966 		nEndY = nRow2 = nRow1;					// nur erste Zeile ansehen
967 		nSrcCount = nCol2 - nCol1 + 1;
968 		nIndex = ((long)nEndX) - nCol1;			// kann negativ werden
969 		if ( nEndX >= nCol1 )
970 			eFillDir = FILL_TO_RIGHT;
971 		else
972 			eFillDir = FILL_TO_LEFT;
973 	}
974 	else										// Richtung nicht eindeutig
975 		bOk = sal_False;
976 
977 	if ( bOk )
978 	{
979 		FillCmd eFillCmd;
980 		FillDateCmd eDateCmd;
981 		double nInc;
982 		sal_uInt16 nMinDigits;
983 		ScUserListData* pListData = NULL;
984 		sal_uInt16 nListIndex;
985 
986 		FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
987 
988 		if ( pListData )							// benutzerdefinierte Liste
989 		{
990 			sal_uInt16 nListCount = pListData->GetSubCount();
991 			if ( nListCount )
992 			{
993 				sal_uLong nSub = nSrcCount - 1;	//	nListIndex ist vom letzten Source-Eintrag
994                 while ( nIndex < sal::static_int_cast<long>(nSub) )
995 					nIndex += nListCount;
996 				sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount;
997                 aValue = pListData->GetSubStr(sal::static_int_cast<sal_uInt16>(nPos));
998 			}
999 		}
1000 		else if ( eFillCmd == FILL_SIMPLE )			// Auffuellen mit Muster
1001 		{
1002 			//Add for i89232
1003 			if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP))
1004 			{
1005 				long nBegin = 0;
1006 				long nEnd = 0;
1007 				if (nEndY > nRow1)
1008 				{
1009 					nBegin = nRow2+1;
1010 					nEnd = nEndY;
1011 				}
1012 				else
1013 				{
1014 					nBegin = nEndY;
1015 					nEnd = nRow1 -1;
1016 				}
1017                 long nNonFiltered = CountNonFilteredRows(nBegin, nEnd);
1018                 long nFiltered = nEnd + 1 - nBegin - nNonFiltered;
1019 				if (nIndex >0)
1020                     nIndex = nIndex - nFiltered;
1021 				else
1022                     nIndex = nIndex + nFiltered;
1023 			}
1024 			//End of i89232
1025 
1026 			long nPosIndex = nIndex;
1027 			while ( nPosIndex < 0 )
1028 				nPosIndex += nSrcCount;
1029 			sal_uLong nPos = nPosIndex % nSrcCount;
1030 			SCCOL nSrcX = nCol1;
1031 			SCROW nSrcY = nRow1;
1032 			if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
1033                 nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) );
1034 			else
1035                 nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) );
1036 
1037 			ScBaseCell*	pCell = GetCell( nSrcX, nSrcY );
1038 			if ( pCell )
1039 			{
1040 				sal_Int32 nDelta;
1041 				if (nIndex >= 0)
1042 					nDelta = nIndex / nSrcCount;
1043 				else
1044 					nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount;	// -1 -> -1
1045 
1046 				CellType eType = pCell->GetCellType();
1047 				switch ( eType )
1048 				{
1049 					case CELLTYPE_STRING:
1050 					case CELLTYPE_EDIT:
1051 					{
1052 						if ( eType == CELLTYPE_STRING )
1053 							((ScStringCell*)pCell)->GetString( aValue );
1054 						else
1055 							((ScEditCell*)pCell)->GetString( aValue );
1056 						if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() )	//i89232
1057 						{
1058 							sal_Int32 nVal;
1059 							sal_uInt16 nCellDigits = 0;	// look at each source cell individually
1060 							short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
1061 							if ( nFlag < 0 )
1062                             {
1063                                 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1064                                     aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta);
1065 
1066 								aValue.Insert( lcl_ValueString( nVal + nDelta, nCellDigits ), 0 );
1067                             }
1068 							else if ( nFlag > 0 )
1069 								aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
1070 						}
1071 					}
1072 					break;
1073 					case CELLTYPE_VALUE:
1074 					{
1075 						//	dabei kann's keinen Ueberlauf geben...
1076 						double nVal = ((ScValueCell*)pCell)->GetValue();
1077 						if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() )	//i89232
1078 							nVal += (double) nDelta;
1079 
1080 						Color* pColor;
1081 						sal_uLong nNumFmt = GetNumberFormat( nSrcX, nSrcY );
1082 						pDocument->GetFormatTable()->
1083 							GetOutputString( nVal, nNumFmt, aValue, &pColor );
1084 					}
1085 					break;
1086 					//	Formeln nicht
1087                     default:
1088                     {
1089                         // added to avoid warnings
1090                     }
1091 				}
1092 			}
1093 		}
1094 		else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE )		// Werte
1095 		{
1096             sal_Bool bValueOk;
1097 			double nStart;
1098             sal_Int32 nVal = 0;
1099 			short nHeadNoneTail = 0;
1100 			ScBaseCell*	pCell = GetCell( nCol1, nRow1 );
1101 			if ( pCell )
1102 			{
1103 				CellType eType = pCell->GetCellType();
1104 				switch ( eType )
1105 				{
1106 					case CELLTYPE_STRING:
1107 					case CELLTYPE_EDIT:
1108 					{
1109 						if ( eType == CELLTYPE_STRING )
1110 							((ScStringCell*)pCell)->GetString( aValue );
1111 						else
1112 							((ScEditCell*)pCell)->GetString( aValue );
1113 						nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
1114 						if ( nHeadNoneTail )
1115 							nStart = (double)nVal;
1116 						else
1117 							nStart = 0.0;
1118 					}
1119 					break;
1120 					case CELLTYPE_VALUE:
1121 						nStart = ((ScValueCell*)pCell)->GetValue();
1122 					break;
1123 					case CELLTYPE_FORMULA:
1124 						nStart = ((ScFormulaCell*)pCell)->GetValue();
1125 					break;
1126 					default:
1127 						nStart = 0.0;
1128 				}
1129 			}
1130 			else
1131 				nStart = 0.0;
1132 			if ( eFillCmd == FILL_LINEAR )
1133 			{
1134 				double nAdd = nInc;
1135                 bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
1136                              SubTotal::SafePlus( nStart, nAdd ) );
1137 			}
1138 			else		// Datum
1139 			{
1140                 bValueOk = sal_True;
1141 				sal_uInt16 nDayOfMonth = 0;
1142 				if ( nIndex < 0 )
1143 				{
1144 					nIndex = -nIndex;
1145 					nInc = -nInc;
1146 				}
1147 				for (long i=0; i<nIndex; i++)
1148 					IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
1149 			}
1150 
1151             if (bValueOk)
1152 			{
1153 				if ( nHeadNoneTail )
1154 				{
1155 					if ( nHeadNoneTail < 0 )
1156                     {
1157                         if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1158                             aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart );
1159 
1160 						aValue.Insert( lcl_ValueString( (sal_Int32)nStart, nMinDigits ), 0 );
1161                     }
1162 					else
1163 						aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits );
1164 				}
1165 				else
1166 				{
1167 					//!	Zahlformat je nach Index holen?
1168 					Color* pColor;
1169 					sal_uLong nNumFmt = GetNumberFormat( nCol1, nRow1 );
1170 					pDocument->GetFormatTable()->
1171 						GetOutputString( nStart, nNumFmt, aValue, &pColor );
1172 				}
1173 			}
1174 		}
1175 		else
1176 		{
1177 			DBG_ERROR("GetAutoFillPreview: falscher Modus");
1178 		}
1179 	}
1180 
1181 	return aValue;
1182 }
1183 
1184 void ScTable::IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd)
1185 {
1186 	if (eCmd == FILL_DAY)
1187 	{
1188 		rVal += nStep;
1189 		return;
1190 	}
1191 
1192 	// class Date Grenzen
1193 	const sal_uInt16 nMinYear = 1583;
1194 	const sal_uInt16 nMaxYear = 9956;
1195 
1196 	long nInc = (long) nStep;		// nach oben/unten begrenzen ?
1197 	Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
1198 	Date aDate = aNullDate;
1199 	aDate += (long)rVal;
1200 	switch (eCmd)
1201 	{
1202 		case FILL_WEEKDAY:
1203 			{
1204 				aDate += nInc;
1205 				DayOfWeek eWeekDay = aDate.GetDayOfWeek();
1206 				if (nInc >= 0)
1207 				{
1208 					if (eWeekDay == SATURDAY)
1209 						aDate += 2;
1210 					else if (eWeekDay == SUNDAY)
1211 						aDate += 1;
1212 				}
1213 				else
1214 				{
1215 					if (eWeekDay == SATURDAY)
1216 						aDate -= 1;
1217 					else if (eWeekDay == SUNDAY)
1218 						aDate -= 2;
1219 				}
1220 			}
1221 			break;
1222 		case FILL_MONTH:
1223 			{
1224 				if ( nDayOfMonth == 0 )
1225 					nDayOfMonth = aDate.GetDay();		// init
1226 				long nMonth = aDate.GetMonth();
1227 				long nYear = aDate.GetYear();
1228 
1229 				nMonth += nInc;
1230 
1231 				if (nInc >= 0)
1232 				{
1233 					if (nMonth > 12)
1234 					{
1235 						long nYAdd = (nMonth-1) / 12;
1236 						nMonth -= nYAdd * 12;
1237 						nYear += nYAdd;
1238 					}
1239 				}
1240 				else
1241 				{
1242 					if (nMonth < 1)
1243 					{
1244 						long nYAdd = 1 - nMonth / 12;		// positiv
1245 						nMonth += nYAdd * 12;
1246 						nYear -= nYAdd;
1247 					}
1248 				}
1249 
1250 				if ( nYear < nMinYear )
1251 					aDate = Date( 1,1, nMinYear );
1252 				else if ( nYear > nMaxYear )
1253 					aDate = Date( 31,12, nMaxYear );
1254 				else
1255 				{
1256 					aDate.SetMonth((sal_uInt16) nMonth);
1257 					aDate.SetYear((sal_uInt16) nYear);
1258 					if ( nDayOfMonth > 28 )
1259 						aDate.SetDay( Min( aDate.GetDaysInMonth(), nDayOfMonth ) );
1260 				}
1261 			}
1262 			break;
1263 		case FILL_YEAR:
1264 			{
1265 				long nYear = aDate.GetYear();
1266 				nYear += nInc;
1267 				if ( nYear < nMinYear )
1268 					aDate = Date( 1,1, nMinYear );
1269 				else if ( nYear > nMaxYear )
1270 					aDate = Date( 31,12, nMaxYear );
1271 				else
1272 					aDate.SetYear((sal_uInt16) nYear);
1273 			}
1274 			break;
1275         default:
1276         {
1277             // added to avoid warnings
1278         }
1279 	}
1280 
1281 	rVal = aDate - aNullDate;
1282 }
1283 
1284 void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1285 					sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1286 					double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits,
1287 					sal_Bool bAttribs, ScProgress& rProgress )
1288 {
1289 	//
1290 	//	Richtung auswerten
1291 	//
1292 
1293 	sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
1294 	sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
1295 
1296     sal_uLong nCol = 0;
1297     sal_uLong nRow = 0;
1298 	sal_uLong& rInner = bVertical ? nRow : nCol;		// Schleifenvariablen
1299 	sal_uLong& rOuter = bVertical ? nCol : nRow;
1300 	sal_uLong nOStart;
1301 	sal_uLong nOEnd;
1302 	sal_uLong nIStart;
1303 	sal_uLong nIEnd;
1304 	sal_uLong nISource;
1305 
1306 	if (bVertical)
1307 	{
1308 		nFillCount += (nRow2 - nRow1);
1309 		if (nFillCount == 0)
1310 			return;
1311 		nOStart = nCol1;
1312 		nOEnd = nCol2;
1313 		if (bPositive)
1314 		{
1315 			nISource = nRow1;
1316 			nIStart = nRow1 + 1;
1317 			nIEnd = nRow1 + nFillCount;
1318 		}
1319 		else
1320 		{
1321 			nISource = nRow2;
1322 			nIStart = nRow2 - 1;
1323 			nIEnd = nRow2 - nFillCount;
1324 		}
1325 	}
1326 	else
1327 	{
1328 		nFillCount += (nCol2 - nCol1);
1329 		if (nFillCount == 0)
1330 			return;
1331 		nOStart = nRow1;
1332 		nOEnd = nRow2;
1333 		if (bPositive)
1334 		{
1335 			nISource = nCol1;
1336 			nIStart = nCol1 + 1;
1337 			nIEnd = nCol1 + nFillCount;
1338 		}
1339 		else
1340 		{
1341 			nISource = nCol2;
1342 			nIStart = nCol2 - 1;
1343 			nIEnd = nCol2 - nFillCount;
1344 		}
1345 	}
1346 
1347 	sal_uLong nIMin = nIStart;
1348 	sal_uLong nIMax = nIEnd;
1349 	PutInOrder(nIMin,nIMax);
1350     sal_uInt16 nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS);
1351 	if (bVertical)
1352 		DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel);
1353 	else
1354 		DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel);
1355 
1356 	sal_uLong nProgress = rProgress.GetState();
1357 
1358 	//
1359 	//	ausfuehren
1360 	//
1361 
1362 	sal_uLong nActFormCnt = 0;
1363 	for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
1364 	{
1365 		sal_Bool bFirst = sal_True;
1366 		rInner = nISource;
1367 		ScBaseCell* pSrcCell = aCol[nCol].GetCell(static_cast<SCROW>(nRow));
1368 
1369 		if (bVertical && bAttribs)
1370 			aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
1371 
1372 		if (bAttribs)
1373 		{
1374 			const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));
1375 			if (bVertical)
1376                 aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin),
1377                         static_cast<SCROW>(nIMax), *pSrcPattern, sal_True );
1378 			else
1379                 for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++)
1380 					aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, sal_True);
1381 		}
1382 
1383 		if (pSrcCell)
1384 		{
1385 			CellType eCellType = pSrcCell->GetCellType();
1386 
1387 			if (eFillCmd == FILL_SIMPLE)				// kopieren
1388 			{
1389 				if (eCellType == CELLTYPE_FORMULA)
1390 				{
1391 					for (rInner = nIMin; rInner <= nIMax; rInner++)
1392 					{
1393 						sal_uLong nInd = nActFormCnt;
1394 						FillFormula(nInd, bFirst, (ScFormulaCell*)pSrcCell,
1395 							static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) );
1396 						bFirst = sal_False;
1397 						rProgress.SetStateOnPercent( ++nProgress );
1398 					}
1399 				}
1400 				else if (eCellType != CELLTYPE_NOTE)
1401 				{
1402 					for (rInner = nIMin; rInner <= nIMax; rInner++)
1403 					{
1404                         ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
1405                         aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
1406 					}
1407 					nProgress += nIMax - nIMin + 1;
1408 					rProgress.SetStateOnPercent( nProgress );
1409 				}
1410 			}
1411 			else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
1412 			{
1413 				double nStartVal;
1414 				if (eCellType == CELLTYPE_VALUE)
1415 					nStartVal = ((ScValueCell*)pSrcCell)->GetValue();
1416 				else
1417 					nStartVal = ((ScFormulaCell*)pSrcCell)->GetValue();
1418 				double nVal = nStartVal;
1419 				long nIndex = 0;
1420 
1421 				sal_Bool bError = sal_False;
1422 				sal_Bool bOverflow = sal_False;
1423 
1424 				sal_uInt16 nDayOfMonth = 0;
1425                 rInner = nIStart;
1426                 while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1427 				{
1428 					if (!bError && !bOverflow)
1429 					{
1430 						switch (eFillCmd)
1431 						{
1432 							case FILL_LINEAR:
1433 								{
1434 									//	#86365# use multiplication instead of repeated addition
1435 									//	to avoid accumulating rounding errors
1436 									nVal = nStartVal;
1437 									double nAdd = nStepValue;
1438 									if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1439 										 !SubTotal::SafePlus( nVal, nAdd ) )
1440 										bError = sal_True;
1441 								}
1442 								break;
1443 							case FILL_GROWTH:
1444 								if (!SubTotal::SafeMult(nVal, nStepValue))
1445 									bError = sal_True;
1446 								break;
1447 							case FILL_DATE:
1448 								if (fabs(nVal) > _D_MAX_LONG_)
1449 									bError = sal_True;
1450 								else
1451 									IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
1452 								break;
1453                             default:
1454                             {
1455                                 // added to avoid warnings
1456                             }
1457 						}
1458 
1459 						if (nStepValue >= 0)
1460 						{
1461 							if (nVal > nMaxValue)			// Zielwert erreicht?
1462 							{
1463 								nVal = nMaxValue;
1464 								bOverflow = sal_True;
1465 							}
1466 						}
1467 						else
1468 						{
1469 							if (nVal < nMaxValue)
1470 							{
1471 								nVal = nMaxValue;
1472 								bOverflow = sal_True;
1473 							}
1474 						}
1475 					}
1476 
1477 					if (bError)
1478 						aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1479 					else if (!bOverflow)
1480 						aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal);
1481 
1482 					if (rInner == nIEnd) break;
1483 					if (bPositive) ++rInner; else --rInner;
1484 				}
1485 				nProgress += nIMax - nIMin + 1;
1486 				rProgress.SetStateOnPercent( nProgress );
1487 			}
1488 			else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
1489 			{
1490 				if ( nStepValue >= 0 )
1491 				{
1492 					if ( nMaxValue >= (double)LONG_MAX )
1493 						nMaxValue = (double)LONG_MAX - 1;
1494 				}
1495 				else
1496 				{
1497 					if ( nMaxValue <= (double)LONG_MIN )
1498 						nMaxValue = (double)LONG_MIN + 1;
1499 				}
1500 				String aValue;
1501 				if (eCellType == CELLTYPE_STRING)
1502 					((ScStringCell*)pSrcCell)->GetString( aValue );
1503 				else
1504 					((ScEditCell*)pSrcCell)->GetString( aValue );
1505 				sal_Int32 nStringValue;
1506 				sal_uInt16 nMinDigits = nArgMinDigits;
1507 				short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
1508 				if ( nHeadNoneTail )
1509 				{
1510 					double nStartVal = (double)nStringValue;
1511 					double nVal = nStartVal;
1512 					long nIndex = 0;
1513 					sal_Bool bError = sal_False;
1514 					sal_Bool bOverflow = sal_False;
1515 
1516                     sal_Bool bIsOrdinalSuffix = aValue.Equals( ScGlobal::GetOrdinalSuffix(
1517                                 (sal_Int32)nStartVal));
1518 
1519                     rInner = nIStart;
1520                     while (true)        // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1521 					{
1522 						if (!bError && !bOverflow)
1523 						{
1524 							switch (eFillCmd)
1525 							{
1526 								case FILL_LINEAR:
1527 									{
1528 										//	#86365# use multiplication instead of repeated addition
1529 										//	to avoid accumulating rounding errors
1530 										nVal = nStartVal;
1531 										double nAdd = nStepValue;
1532 										if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1533 											 !SubTotal::SafePlus( nVal, nAdd ) )
1534 											bError = sal_True;
1535 									}
1536 									break;
1537 								case FILL_GROWTH:
1538 									if (!SubTotal::SafeMult(nVal, nStepValue))
1539 										bError = sal_True;
1540 									break;
1541                                 default:
1542                                 {
1543                                     // added to avoid warnings
1544                                 }
1545 							}
1546 
1547 							if (nStepValue >= 0)
1548 							{
1549 								if (nVal > nMaxValue)			// Zielwert erreicht?
1550 								{
1551 									nVal = nMaxValue;
1552 									bOverflow = sal_True;
1553 								}
1554 							}
1555 							else
1556 							{
1557 								if (nVal < nMaxValue)
1558 								{
1559 									nVal = nMaxValue;
1560 									bOverflow = sal_True;
1561 								}
1562 							}
1563 						}
1564 
1565 						if (bError)
1566 							aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1567 						else if (!bOverflow)
1568 						{
1569 							nStringValue = (sal_Int32)nVal;
1570 							String aStr;
1571 							if ( nHeadNoneTail < 0 )
1572 							{
1573                                 aCol[nCol].Insert( static_cast<SCROW>(nRow),
1574                                         lcl_getSuffixCell( pDocument,
1575                                             nStringValue, nMinDigits, aValue,
1576                                             eCellType, bIsOrdinalSuffix ));
1577 							}
1578 							else
1579 							{
1580 								aStr = aValue;
1581 								aStr += lcl_ValueString( nStringValue, nMinDigits );
1582 								ScStringCell* pCell = new ScStringCell( aStr );
1583 								aCol[nCol].Insert( static_cast<SCROW>(nRow), pCell );
1584 							}
1585 						}
1586 
1587 						if (rInner == nIEnd) break;
1588 						if (bPositive) ++rInner; else --rInner;
1589 					}
1590 				}
1591 				nProgress += nIMax - nIMin + 1;
1592 				rProgress.SetStateOnPercent( nProgress );
1593 			}
1594 		}
1595 		else
1596 		{
1597 			nProgress += nIMax - nIMin + 1;
1598 			rProgress.SetStateOnPercent( nProgress );
1599 		}
1600 		++nActFormCnt;
1601 	}
1602 }
1603 
1604 void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1605 					sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1606 					double nStepValue, double nMaxValue)
1607 {
1608 	sal_uLong nProgCount;
1609 	if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP)
1610 		nProgCount = nCol2 - nCol1 + 1;
1611 	else
1612 		nProgCount = nRow2 - nRow1 + 1;
1613 	nProgCount *= nFillCount;
1614 	ScProgress aProgress( pDocument->GetDocumentShell(),
1615 							ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
1616 
1617 	bSharedNameInserted = sal_False;
1618 
1619 	if (eFillCmd == FILL_AUTO)
1620 		FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress);
1621 	else
1622 		FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
1623 					eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, sal_True, aProgress);
1624 
1625 	if (bSharedNameInserted)						// Wurde Shared-Name eingefuegt?
1626 		pDocument->GetRangeName()->SetSharedMaxIndex(
1627 			pDocument->GetRangeName()->GetSharedMaxIndex()+1);	// dann hochzaehlen
1628 }
1629 
1630 
1631 void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1632 								const ScPatternAttr& rAttr, sal_uInt16 nFormatNo)
1633 {
1634 	ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1635 	if (pAutoFormat)
1636 	{
1637 		ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1638 		if (pData)
1639 		{
1640 //			ScPatternAttr aPattern(pDocument->GetPool());
1641 //            pData->FillToItemSet(nIndex, aPattern.GetItemSet(), *pDocument);
1642 			ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr);
1643 		}
1644 	}
1645 }
1646 
1647 void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1648 							sal_uInt16 nFormatNo )
1649 {
1650 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1651 	{
1652 		ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1653 		if (pAutoFormat)
1654 		{
1655             ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1656 			if (pData)
1657 			{
1658                 ScPatternAttr* pPatternAttrs[16];
1659                 for (sal_uInt8 i = 0; i < 16; ++i)
1660                 {
1661                     pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool());
1662                     pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument);
1663                 }
1664 
1665 				SCCOL nCol = nStartCol;
1666 				SCROW nRow = nStartRow;
1667 				sal_uInt16 nIndex = 0;
1668 				// Linke obere Ecke
1669 				AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1670 				// Linke Spalte
1671 				if (pData->IsEqualData(4, 8))
1672 					AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo);
1673 				else
1674 				{
1675 					nIndex = 4;
1676 					for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1677 					{
1678 						AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1679 						if (nIndex == 4)
1680 							nIndex = 8;
1681 						else
1682 							nIndex = 4;
1683 					}
1684 				}
1685 				// Linke untere Ecke
1686 				nRow = nEndRow;
1687 				nIndex = 12;
1688 				AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1689 				// Rechte obere Ecke
1690 				nCol = nEndCol;
1691 				nRow = nStartRow;
1692 				nIndex = 3;
1693 				AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1694 				// Rechte Spalte
1695 				if (pData->IsEqualData(7, 11))
1696 					AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo);
1697 				else
1698 				{
1699 					nIndex = 7;
1700 					for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1701 					{
1702 						AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1703 						if (nIndex == 7)
1704 							nIndex = 11;
1705 						else
1706 							nIndex = 7;
1707 					}
1708 				}
1709 				// Rechte untere Ecke
1710 				nRow = nEndRow;
1711 				nIndex = 15;
1712 				AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1713 				nRow = nStartRow;
1714 				nIndex = 1;
1715 				for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1716 				{
1717 					AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1718 					if (nIndex == 1)
1719 						nIndex = 2;
1720 					else
1721 						nIndex = 1;
1722 				}
1723 				// Untere Zeile
1724 				nRow = nEndRow;
1725 				nIndex = 13;
1726 				for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1727 				{
1728 					AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1729 					if (nIndex == 13)
1730 						nIndex = 14;
1731 					else
1732 						nIndex = 13;
1733 				}
1734 				// Boddy
1735 				if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
1736 					AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo);
1737 				else
1738 				{
1739 					if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
1740 					{
1741 						nIndex = 5;
1742 						for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1743 						{
1744 							AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo);
1745 							if (nIndex == 5)
1746 								nIndex = 6;
1747 							else
1748 								nIndex = 5;
1749 						}
1750 					}
1751 					else
1752 					{
1753 						nIndex = 5;
1754 						for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1755 						{
1756 							for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1757 							{
1758 								AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1759 								if ((nIndex == 5) || (nIndex == 9))
1760 								{
1761 									if (nIndex == 5)
1762 										nIndex = 9;
1763 									else
1764 										nIndex = 5;
1765 								}
1766 								else
1767 								{
1768 									if (nIndex == 6)
1769 										nIndex = 10;
1770 									else
1771 										nIndex = 6;
1772 								}
1773 							} // for nRow
1774 							if ((nIndex == 5) || (nIndex == 9))
1775 								nIndex = 6;
1776 							else
1777 								nIndex = 5;
1778 						} // for nCol
1779 					} // if not equal Column
1780 				} // if not all equal
1781 
1782                 for (sal_uInt8 j = 0; j < 16; ++j)
1783                     delete pPatternAttrs[j];
1784 			} // if AutoFormatData != NULL
1785 		} // if AutoFormat != NULL
1786 	} // if ValidColRow
1787 }
1788 
1789 void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData)
1790 {
1791 	sal_uInt32 nFormatIndex = GetNumberFormat( nCol, nRow );
1792 	ScNumFormatAbbrev 	aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
1793     rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat );
1794 }
1795 
1796 #define LF_LEFT         1
1797 #define LF_TOP          2
1798 #define LF_RIGHT        4
1799 #define LF_BOTTOM       8
1800 #define LF_ALL          (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1801 
1802 void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData)
1803 {
1804 	const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER);
1805 	const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER);
1806 	const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER);
1807 	const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER);
1808 	const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER);
1809 
1810     SvxBoxItem aBox( ATTR_BORDER );
1811 	if (nFlags & LF_LEFT)
1812 	{
1813 		if (pLeftBox)
1814 		{
1815 			if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
1816 				aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1817 			else
1818 				aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT);
1819 		}
1820 		else
1821 			aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1822 	}
1823 	if (nFlags & LF_TOP)
1824 	{
1825 		if (pTopBox)
1826 		{
1827 			if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
1828 				aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1829 			else
1830 				aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP);
1831 		}
1832 		else
1833 			aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1834 	}
1835 	if (nFlags & LF_RIGHT)
1836 	{
1837 		if (pRightBox)
1838 		{
1839 			if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
1840 				aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1841 			else
1842 				aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT);
1843 		}
1844 		else
1845 			aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1846 	}
1847 	if (nFlags & LF_BOTTOM)
1848 	{
1849 		if (pBottomBox)
1850 		{
1851 			if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
1852 				aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1853 			else
1854 				aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM);
1855 		}
1856 		else
1857 			aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1858 	}
1859     rData.PutItem( nIndex, aBox );
1860 }
1861 
1862 void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData)
1863 {
1864 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1865 	{
1866 		if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
1867 		{
1868 			// Linke obere Ecke
1869 			GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
1870 			GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
1871 			// Linke Spalte
1872 			GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
1873 			GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
1874 			GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
1875 			if (nEndRow - nStartRow >= 4)
1876 				GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
1877 			else
1878                 rData.CopyItem( 8, 4, ATTR_BORDER );
1879 			// Linke untere Ecke
1880 			GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
1881 			GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
1882 			// Rechte obere Ecke
1883 			GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
1884 			GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
1885 			// Rechte Spalte
1886 			GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
1887 			GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
1888 			GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
1889 			if (nEndRow - nStartRow >= 4)
1890 				GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
1891 			else
1892                 rData.CopyItem( 11, 7, ATTR_BORDER );
1893 			// Rechte untere Ecke
1894 			GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
1895 			GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
1896 			// Ober Zeile
1897 			GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
1898 			GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
1899 			GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
1900 			if (nEndCol - nStartCol >= 4)
1901 				GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
1902 			else
1903                 rData.CopyItem( 2, 1, ATTR_BORDER );
1904 			// Untere Zeile
1905 			GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
1906 			GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
1907 			GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
1908 			if (nEndCol - nStartCol >= 4)
1909 				GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
1910 			else
1911                 rData.CopyItem( 14, 13, ATTR_BORDER );
1912 			// Body
1913 			GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
1914 			GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
1915 			GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
1916 			GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
1917 			GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
1918 			if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
1919 			{
1920 				GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
1921 				GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
1922 				GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
1923 			}
1924 			else
1925 			{
1926                 rData.CopyItem( 6, 5, ATTR_BORDER );
1927                 rData.CopyItem( 9, 5, ATTR_BORDER );
1928                 rData.CopyItem( 10, 5, ATTR_BORDER );
1929 			}
1930 		}
1931 	}
1932 }
1933 
1934 void ScTable::SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError)
1935 {
1936 	if (ValidColRow(nCol, nRow))
1937 		aCol[nCol].SetError( nRow, nError );
1938 }
1939 
1940 void ScTable::UpdateInsertTabAbs(SCTAB nTable)
1941 {
1942 	for (SCCOL i=0; i <= MAXCOL; i++)
1943 		aCol[i].UpdateInsertTabAbs(nTable);
1944 }
1945 
1946 //UNUSED2008-05  sal_uInt16 ScTable::GetErrorData( SCCOL nCol, SCROW nRow ) const
1947 //UNUSED2008-05  {
1948 //UNUSED2008-05      if (ValidColRow(nCol,nRow))
1949 //UNUSED2008-05          return aCol[nCol].GetErrorData( nRow );
1950 //UNUSED2008-05      else
1951 //UNUSED2008-05          return 0;
1952 //UNUSED2008-05  }
1953 
1954 sal_Bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, sal_Bool bInSel,
1955 									const ScMarkData& rMark) const
1956 {
1957 	if (rRow == MAXROW+2)						// Tabellenende
1958 	{
1959 		rRow = 0;
1960 		rCol = 0;
1961 	}
1962 	else
1963 	{
1964 		rRow++;
1965 		if (rRow == MAXROW+1)
1966 		{
1967 			rCol++;
1968 			rRow = 0;
1969 		}
1970 	}
1971 	if (rCol == MAXCOL+1)
1972 		return sal_True;
1973 	else
1974 	{
1975 		sal_Bool bStop = sal_False;
1976 		while (!bStop)
1977 		{
1978 			if (ValidCol(rCol))
1979 			{
1980 				bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
1981 				if (bStop)
1982 					return sal_True;
1983 				else /*if (rRow == MAXROW+1) */
1984 				{
1985 					rCol++;
1986 					rRow = 0;
1987 				}
1988 			}
1989 			else
1990 				return sal_True;
1991 		}
1992 	}
1993 	return sal_False;
1994 }
1995 
1996 void ScTable::RemoveAutoSpellObj()
1997 {
1998 	for (SCCOL i=0; i <= MAXCOL; i++)
1999 		aCol[i].RemoveAutoSpellObj();
2000 }
2001 
2002 sal_Bool ScTable::TestTabRefAbs(SCTAB nTable)
2003 {
2004 	sal_Bool bRet = sal_False;
2005 	for (SCCOL i=0; i <= MAXCOL; i++)
2006 		if (aCol[i].TestTabRefAbs(nTable))
2007 			bRet = sal_True;
2008 	return bRet;
2009 }
2010 
2011 void ScTable::CompileDBFormula()
2012 {
2013 	for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula();
2014 }
2015 
2016 void ScTable::CompileDBFormula( sal_Bool bCreateFormulaString )
2017 {
2018 	for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString );
2019 }
2020 
2021 void ScTable::CompileNameFormula( sal_Bool bCreateFormulaString )
2022 {
2023 	for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString );
2024 }
2025 
2026 void ScTable::CompileColRowNameFormula()
2027 {
2028 	for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula();
2029 }
2030 
2031 
2032 
2033 
2034 
2035 
2036