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