xref: /aoo41x/main/sc/source/core/data/table2.cxx (revision 4d7c9de0)
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 // INCLUDE ---------------------------------------------------------------
28 
29 #include "scitems.hxx"
30 #include <editeng/boxitem.hxx>
31 #include <tools/urlobj.hxx>
32 #include <svl/poolcach.hxx>
33 #include <unotools/charclass.hxx>
34 #include <math.h>
35 #include <svl/PasswordHelper.hxx>
36 #include <unotools/transliterationwrapper.hxx>
37 
38 #include "patattr.hxx"
39 #include "docpool.hxx"
40 #include "cell.hxx"
41 #include "document.hxx"
42 #include "drwlayer.hxx"
43 #include "olinetab.hxx"
44 #include "rechead.hxx"
45 #include "stlpool.hxx"
46 #include "attarray.hxx"		// Iterator
47 #include "markdata.hxx"
48 #include "progress.hxx"
49 #include "dociter.hxx"
50 #include "conditio.hxx"
51 #include "chartlis.hxx"
52 #include "fillinfo.hxx"
53 #include "bcaslot.hxx"
54 #include "postit.hxx"
55 #include "sheetevents.hxx"
56 #include "globstr.hrc"
57 #include "segmenttree.hxx"
58 #include "dbcolect.hxx"
59 
60 #include <math.h>
61 
62 // STATIC DATA -----------------------------------------------------------
63 
64 
65 sal_Bool ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline )
66 {
67 	sal_uInt16 nOldSizeX = 0;
68 	sal_uInt16 nOldSizeY = 0;
69 	sal_uInt16 nNewSizeX = 0;
70 	sal_uInt16 nNewSizeY = 0;
71 
72 	if (pOutlineTable)
73 	{
74 		nOldSizeX = pOutlineTable->GetColArray()->GetDepth();
75 		nOldSizeY = pOutlineTable->GetRowArray()->GetDepth();
76 		delete pOutlineTable;
77 	}
78 
79 	if (pNewOutline)
80 	{
81 		pOutlineTable = new ScOutlineTable( *pNewOutline );
82 		nNewSizeX = pOutlineTable->GetColArray()->GetDepth();
83 		nNewSizeY = pOutlineTable->GetRowArray()->GetDepth();
84 	}
85 	else
86 		pOutlineTable = NULL;
87 
88 	return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY );		// Groesse geaendert ?
89 }
90 
91 
92 void ScTable::StartOutlineTable()
93 {
94 	if (!pOutlineTable)
95 		pOutlineTable = new ScOutlineTable;
96 }
97 
98 
99 void ScTable::SetSheetEvents( const ScSheetEvents* pNew )
100 {
101     delete pSheetEvents;
102     if (pNew)
103         pSheetEvents = new ScSheetEvents(*pNew);
104     else
105         pSheetEvents = NULL;
106 
107     SetCalcNotification( sal_False );       // discard notifications before the events were set
108 
109     if (IsStreamValid())
110         SetStreamValid(sal_False);
111 }
112 
113 
114 void ScTable::SetCalcNotification( sal_Bool bSet )
115 {
116     bCalcNotification = bSet;
117 }
118 
119 
120 sal_Bool ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize )
121 {
122 	sal_Bool bTest = sal_True;
123 
124 	if ( nStartCol==0 && nEndCol==MAXCOL && pOutlineTable )
125 		bTest = pOutlineTable->TestInsertRow(nSize);
126 
127 	for (SCCOL i=nStartCol; (i<=nEndCol) && bTest; i++)
128 		bTest = aCol[i].TestInsertRow( nSize );
129 
130 	return bTest;
131 }
132 
133 
134 void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize )
135 {
136 	IncRecalcLevel();
137     InitializeNoteCaptions();
138 	if (nStartCol==0 && nEndCol==MAXCOL)
139 	{
140         if (mpRowHeights && pRowFlags)
141 		{
142             mpRowHeights->insertSegment(nStartRow, nSize, false);
143             sal_uInt8 nNewFlags = pRowFlags->Insert( nStartRow, nSize);
144             // only copy manual size flag, clear all others
145             if (nNewFlags && (nNewFlags != CR_MANUALSIZE))
146                 pRowFlags->SetValue( nStartRow, nStartRow + nSize - 1,
147                         nNewFlags & CR_MANUALSIZE);
148 		}
149 
150 		if (pOutlineTable)
151 			pOutlineTable->InsertRow( nStartRow, nSize );
152 
153         mpFilteredRows->insertSegment(nStartRow, nSize, true);
154         mpHiddenRows->insertSegment(nStartRow, nSize, true);
155 
156         if (!maRowManualBreaks.empty())
157         {
158             std::set<SCROW>::reverse_iterator rit = maRowManualBreaks.rbegin();
159             while (rit != maRowManualBreaks.rend())
160             {
161                 SCROW nRow = *rit;
162                 if (nRow < nStartRow)
163                     break;  // while
164                 else
165                 {
166                     maRowManualBreaks.erase( (++rit).base());
167                     maRowManualBreaks.insert( static_cast<SCROW>( nRow + nSize));
168                 }
169             }
170         }
171 	}
172 
173 	for (SCCOL j=nStartCol; j<=nEndCol; j++)
174 		aCol[j].InsertRow( nStartRow, nSize );
175 	DecRecalcLevel( false );
176 
177     InvalidatePageBreaks();
178 }
179 
180 
181 void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize,
182 							sal_Bool* pUndoOutline )
183 {
184 	IncRecalcLevel();
185     InitializeNoteCaptions();
186 	if (nStartCol==0 && nEndCol==MAXCOL)
187 	{
188         if (pRowFlags)
189             pRowFlags->Remove( nStartRow, nSize);
190 
191         if (mpRowHeights)
192             mpRowHeights->removeSegment(nStartRow, nStartRow+nSize);
193 
194 		if (pOutlineTable)
195 			if (pOutlineTable->DeleteRow( nStartRow, nSize ))
196 				if (pUndoOutline)
197 					*pUndoOutline = sal_True;
198 
199         mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize);
200         mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize);
201 
202         if (!maRowManualBreaks.empty())
203         {
204             std::set<SCROW>::iterator it = maRowManualBreaks.upper_bound( static_cast<SCROW>( nStartRow + nSize - 1));
205             maRowManualBreaks.erase( maRowManualBreaks.lower_bound( nStartRow), it);
206             while (it != maRowManualBreaks.end())
207             {
208                 SCROW nRow = *it;
209                 maRowManualBreaks.erase( it++);
210                 maRowManualBreaks.insert( static_cast<SCROW>( nRow - nSize));
211             }
212         }
213 	}
214 
215     {   // scope for bulk broadcast
216         ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
217         for (SCCOL j=nStartCol; j<=nEndCol; j++)
218             aCol[j].DeleteRow( nStartRow, nSize );
219     }
220 	DecRecalcLevel();
221 
222     InvalidatePageBreaks();
223 }
224 
225 
226 sal_Bool ScTable::TestInsertCol( SCROW nStartRow, SCROW nEndRow, SCSIZE nSize )
227 {
228 	sal_Bool bTest = sal_True;
229 
230 	if ( nStartRow==0 && nEndRow==MAXROW && pOutlineTable )
231 		bTest = pOutlineTable->TestInsertCol(nSize);
232 
233 	if ( nSize > static_cast<SCSIZE>(MAXCOL) )
234 		bTest = sal_False;
235 
236 	for (SCCOL i=MAXCOL; (i+static_cast<SCCOL>(nSize)>MAXCOL) && bTest; i--)
237 		bTest = aCol[i].TestInsertCol(nStartRow, nEndRow);
238 
239 	return bTest;
240 }
241 
242 
243 void ScTable::InsertCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize )
244 {
245 	IncRecalcLevel();
246     InitializeNoteCaptions();
247 	if (nStartRow==0 && nEndRow==MAXROW)
248 	{
249 		if (pColWidth && pColFlags)
250         {
251             memmove( &pColWidth[nStartCol+nSize], &pColWidth[nStartCol],
252                     (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
253             memmove( &pColFlags[nStartCol+nSize], &pColFlags[nStartCol],
254                     (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
255         }
256 		if (pOutlineTable)
257 			pOutlineTable->InsertCol( nStartCol, nSize );
258 
259         mpHiddenCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true);
260         mpFilteredCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true);
261 
262         if (!maColManualBreaks.empty())
263         {
264             std::set<SCCOL>::reverse_iterator rit = maColManualBreaks.rbegin();
265             while (rit != maColManualBreaks.rend())
266             {
267                 SCCOL nCol = *rit;
268                 if (nCol < nStartCol)
269                     break;  // while
270                 else
271                 {
272                     maColManualBreaks.erase( (++rit).base());
273                     maColManualBreaks.insert( static_cast<SCCOL>( nCol + nSize));
274                 }
275             }
276         }
277 	}
278 
279 
280 	if ((nStartRow == 0) && (nEndRow == MAXROW))
281 	{
282 		for (SCSIZE i=0; i < nSize; i++)
283 			for (SCCOL nCol = MAXCOL; nCol > nStartCol; nCol--)
284 				aCol[nCol].SwapCol(aCol[nCol-1]);
285 	}
286 	else
287 	{
288 		for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++)
289 			aCol[MAXCOL - nSize - i].MoveTo(nStartRow, nEndRow, aCol[MAXCOL - i]);
290 	}
291 
292 	if (nStartCol>0)						// copy old attributes
293 	{
294 		sal_uInt16 nWhichArray[2];
295 		nWhichArray[0] = ATTR_MERGE;
296 		nWhichArray[1] = 0;
297 
298 		for (SCSIZE i=0; i<nSize; i++)
299 		{
300 			aCol[nStartCol-1].CopyToColumn( nStartRow, nEndRow, IDF_ATTRIB,
301 												sal_False, aCol[nStartCol+i] );
302 			aCol[nStartCol+i].RemoveFlags( nStartRow, nEndRow,
303 												SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
304 			aCol[nStartCol+i].ClearItems( nStartRow, nEndRow, nWhichArray );
305 		}
306 	}
307 	DecRecalcLevel();
308 
309     InvalidatePageBreaks();
310 }
311 
312 
313 void ScTable::DeleteCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize,
314 							sal_Bool* pUndoOutline )
315 {
316 	IncRecalcLevel();
317     InitializeNoteCaptions();
318 	if (nStartRow==0 && nEndRow==MAXROW)
319 	{
320 		if (pColWidth && pColFlags)
321         {
322             memmove( &pColWidth[nStartCol], &pColWidth[nStartCol+nSize],
323                     (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
324             memmove( &pColFlags[nStartCol], &pColFlags[nStartCol+nSize],
325                     (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
326         }
327 		if (pOutlineTable)
328 			if (pOutlineTable->DeleteCol( nStartCol, nSize ))
329 				if (pUndoOutline)
330 					*pUndoOutline = sal_True;
331 
332         SCCOL nRmSize = nStartCol + static_cast<SCCOL>(nSize);
333         mpHiddenCols->removeSegment(nStartCol, nRmSize);
334         mpFilteredCols->removeSegment(nStartCol, nRmSize);
335 
336         if (!maColManualBreaks.empty())
337         {
338             std::set<SCCOL>::iterator it = maColManualBreaks.upper_bound( static_cast<SCCOL>( nStartCol + nSize - 1));
339             maColManualBreaks.erase( maColManualBreaks.lower_bound( nStartCol), it);
340             while (it != maColManualBreaks.end())
341             {
342                 SCCOL nCol = *it;
343                 maColManualBreaks.erase( it++);
344                 maColManualBreaks.insert( static_cast<SCCOL>( nCol - nSize));
345             }
346         }
347 	}
348 
349 
350     {   // scope for bulk broadcast
351         ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
352         for (SCSIZE i = 0; i < nSize; i++)
353             aCol[nStartCol + i].DeleteArea(nStartRow, nEndRow, IDF_ALL);
354     }
355 
356 	if ((nStartRow == 0) && (nEndRow == MAXROW))
357 	{
358 		for (SCSIZE i=0; i < nSize; i++)
359 			for (SCCOL nCol = nStartCol; nCol < MAXCOL; nCol++)
360 				aCol[nCol].SwapCol(aCol[nCol+1]);
361 	}
362 	else
363 	{
364 		for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++)
365 			aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]);
366 	}
367 	DecRecalcLevel();
368 
369     InvalidatePageBreaks();
370 }
371 
372 
373 void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nDelFlag)
374 {
375 	if (nCol2 > MAXCOL) nCol2 = MAXCOL;
376 	if (nRow2 > MAXROW) nRow2 = MAXROW;
377 	if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
378 	{
379 //		IncRecalcLevel();
380 
381         {   // scope for bulk broadcast
382             ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
383             for (SCCOL i = nCol1; i <= nCol2; i++)
384                 aCol[i].DeleteArea(nRow1, nRow2, nDelFlag);
385         }
386 
387 			//
388 			// Zellschutz auf geschuetzter Tabelle nicht setzen
389 			//
390 
391 		if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
392 		{
393 			ScPatternAttr aPattern(pDocument->GetPool());
394 			aPattern.GetItemSet().Put( ScProtectionAttr( sal_False ) );
395 			ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
396 		}
397 
398 //		DecRecalcLevel();
399 	}
400 }
401 
402 
403 void ScTable::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
404 {
405     {   // scope for bulk broadcast
406         ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
407         for (SCCOL i=0; i<=MAXCOL; i++)
408             aCol[i].DeleteSelection( nDelFlag, rMark );
409     }
410 
411 		//
412 		// Zellschutz auf geschuetzter Tabelle nicht setzen
413 		//
414 
415 	if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
416 	{
417 		ScDocumentPool* pPool = pDocument->GetPool();
418 		SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END );
419 		aSet.Put( ScProtectionAttr( sal_False ) );
420 		SfxItemPoolCache aCache( pPool, &aSet );
421 		ApplySelectionCache( &aCache, rMark );
422 	}
423 }
424 
425 
426 //	pTable = Clipboard
427 void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
428                         ScTable* pTable, sal_Bool bKeepScenarioFlags, sal_Bool bCloneNoteCaptions)
429 {
430 	if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
431 	{
432 		//	Inhalte kopieren
433 		SCCOL i;
434 
435 		for ( i = nCol1; i <= nCol2; i++)
436             aCol[i].CopyToClip(nRow1, nRow2, pTable->aCol[i], bKeepScenarioFlags, bCloneNoteCaptions);
437 
438 		//	copy widths/heights, and only "hidden", "filtered" and "manual" flags
439 		//	also for all preceding columns/rows, to have valid positions for drawing objects
440 
441 		if (pColWidth && pTable->pColWidth)
442 			for (i=0; i<=nCol2; i++)
443 				pTable->pColWidth[i] = pColWidth[i];
444 
445         pTable->CopyColHidden(*this, 0, nCol2);
446         pTable->CopyColFiltered(*this, 0, nCol2);
447 
448         if (pRowFlags && pTable->pRowFlags && mpRowHeights && pTable->mpRowHeights)
449         {
450             pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, CR_MANUALSIZE);
451             pTable->CopyRowHeight(*this, 0, nRow2, 0);
452         }
453 
454         pTable->CopyRowHidden(*this, 0, nRow2);
455         pTable->CopyRowFiltered(*this, 0, nRow2);
456 
457 		//	ggf. Formeln durch Werte ersetzen
458 
459 		if ( IsProtected() )
460 			for (i = nCol1; i <= nCol2; i++)
461 				pTable->aCol[i].RemoveProtected(nRow1, nRow2);
462 	}
463 }
464 
465 void ScTable::CopyToClip(const ScRangeList& rRanges, ScTable* pTable,
466                          bool bKeepScenarioFlags, bool bCloneNoteCaptions)
467 {
468     ScRangeList aRanges(rRanges);
469     for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next())
470     {
471         CopyToClip(p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(),
472                    pTable, bKeepScenarioFlags, bCloneNoteCaptions);
473     }
474 }
475 
476 void ScTable::CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
477 							SCsCOL nDx, SCsROW nDy, sal_uInt16 nInsFlag,
478 							sal_Bool bAsLink, sal_Bool bSkipAttrForEmpty, ScTable* pTable)
479 {
480 	SCCOL i;
481 
482 	if (nCol2 > MAXCOL) nCol2 = MAXCOL;
483 	if (nRow2 > MAXROW) nRow2 = MAXROW;
484 	if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
485 	{
486 		IncRecalcLevel();
487 		for ( i = nCol1; i <= nCol2; i++)
488 			aCol[i].CopyFromClip(nRow1, nRow2, nDy, nInsFlag, bAsLink, bSkipAttrForEmpty, pTable->aCol[i - nDx]);
489 
490 		if ((nInsFlag & IDF_ATTRIB) != 0)
491 		{
492 			if (nRow1==0 && nRow2==MAXROW && pColWidth && pTable->pColWidth)
493 				for (i=nCol1; i<=nCol2; i++)
494 					pColWidth[i] = pTable->pColWidth[i-nDx];
495 
496             if (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pTable->mpRowHeights &&
497 											 pRowFlags && pTable->pRowFlags)
498             {
499                 CopyRowHeight(*pTable, nRow1, nRow2, -nDy);
500                 // Must copy CR_MANUALSIZE bit too, otherwise pRowHeight doesn't make sense
501 				for (SCROW j=nRow1; j<=nRow2; j++)
502 				{
503 					if ( pTable->pRowFlags->GetValue(j-nDy) & CR_MANUALSIZE )
504 						pRowFlags->OrValue( j, CR_MANUALSIZE);
505 					else
506                         pRowFlags->AndValue( j, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
507 				}
508             }
509 
510 				//
511 				// Zellschutz auf geschuetzter Tabelle nicht setzen
512 				//
513 
514 			if ( IsProtected() && (nInsFlag & IDF_ATTRIB) )
515 			{
516 				ScPatternAttr aPattern(pDocument->GetPool());
517 				aPattern.GetItemSet().Put( ScProtectionAttr( sal_False ) );
518 				ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
519 			}
520 		}
521 		DecRecalcLevel();
522 	}
523 }
524 
525 
526 void ScTable::MixData( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
527 							sal_uInt16 nFunction, sal_Bool bSkipEmpty, ScTable* pSrcTab )
528 {
529 	for (SCCOL i=nCol1; i<=nCol2; i++)
530 		aCol[i].MixData( nRow1, nRow2, nFunction, bSkipEmpty, pSrcTab->aCol[i] );
531 }
532 
533 
534 //	Markierung von diesem Dokument
535 void ScTable::MixMarked( const ScMarkData& rMark, sal_uInt16 nFunction,
536 						sal_Bool bSkipEmpty, ScTable* pSrcTab )
537 {
538 	for (SCCOL i=0; i<=MAXCOL; i++)
539 		aCol[i].MixMarked( rMark, nFunction, bSkipEmpty, pSrcTab->aCol[i] );
540 }
541 
542 
543 void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
544 								ScTable* pTransClip, sal_uInt16 nFlags, sal_Bool bAsLink )
545 {
546 	sal_Bool bWasCut = pDocument->IsCutMode();
547 
548 	ScDocument* pDestDoc = pTransClip->pDocument;
549 
550 	for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
551 	{
552 		SCROW nRow;
553 		ScBaseCell* pCell;
554 
555 		if ( bAsLink && nFlags == IDF_ALL )
556 		{
557 			//	#68989# with IDF_ALL, also create links (formulas) for empty cells
558 
559 			for ( nRow=nRow1; nRow<=nRow2; nRow++ )
560 			{
561 				//	create simple formula, as in ScColumn::CreateRefCell
562 
563 				ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
564 				ScSingleRefData aRef;
565 				aRef.nCol = nCol;
566 				aRef.nRow = nRow;
567 				aRef.nTab = nTab;
568 				aRef.InitFlags();							// -> all absolute
569 				aRef.SetFlag3D(sal_True);
570 				aRef.CalcRelFromAbs( aDestPos );
571 				ScTokenArray aArr;
572 				aArr.AddSingleReference( aRef );
573 
574 				ScBaseCell* pNew = new ScFormulaCell( pDestDoc, aDestPos, &aArr );
575 				pTransClip->PutCell( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pNew );
576 			}
577 		}
578 		else
579 		{
580 			ScColumnIterator aIter( &aCol[nCol], nRow1, nRow2 );
581 			while (aIter.Next( nRow, pCell ))
582 			{
583                 ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
584 				ScBaseCell* pNew;
585 				if ( bAsLink )					// Referenz erzeugen ?
586 				{
587 					pNew = aCol[nCol].CreateRefCell( pDestDoc, aDestPos, aIter.GetIndex(), nFlags );
588 				}
589 				else							// kopieren
590 				{
591                     ScAddress aOwnPos( nCol, nRow, nTab );
592 					if (pCell->GetCellType() == CELLTYPE_FORMULA)
593 					{
594                         pNew = pCell->CloneWithNote( aOwnPos, *pDestDoc, aDestPos, SC_CLONECELL_STARTLISTENING );
595 
596 						//	Referenzen drehen
597 						//	bei Cut werden Referenzen spaeter per UpdateTranspose angepasst
598 
599 						if (!bWasCut)
600 							((ScFormulaCell*)pNew)->TransposeReference();
601 					}
602 					else
603                     {
604                         pNew = pCell->CloneWithNote( aOwnPos, *pDestDoc, aDestPos );
605                     }
606 				}
607 				pTransClip->PutCell( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pNew );
608 			}
609 		}
610 
611 		//	Attribute
612 
613 		SCROW nAttrRow1;
614 		SCROW nAttrRow2;
615 		const ScPatternAttr* pPattern;
616 		ScAttrIterator* pAttrIter = aCol[nCol].CreateAttrIterator( nRow1, nRow2 );
617 		while ( (pPattern = pAttrIter->Next( nAttrRow1, nAttrRow2 )) != 0 )
618 		{
619 			if ( !IsDefaultItem( pPattern ) )
620 			{
621 				const SfxItemSet& rSet = pPattern->GetItemSet();
622 				if ( rSet.GetItemState( ATTR_MERGE, sal_False ) == SFX_ITEM_DEFAULT &&
623 					 rSet.GetItemState( ATTR_MERGE_FLAG, sal_False ) == SFX_ITEM_DEFAULT &&
624 					 rSet.GetItemState( ATTR_BORDER, sal_False ) == SFX_ITEM_DEFAULT )
625 				{
626 					// no borders or merge items involved - use pattern as-is
627 					for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
628 						pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), *pPattern, sal_True );
629 				}
630 				else
631 				{
632 					// transpose borders and merge values, remove merge flags (refreshed after pasting)
633 					ScPatternAttr aNewPattern( *pPattern );
634 					SfxItemSet& rNewSet = aNewPattern.GetItemSet();
635 
636 					const SvxBoxItem& rOldBox = (const SvxBoxItem&)rSet.Get(ATTR_BORDER);
637 					if ( rOldBox.GetTop() || rOldBox.GetBottom() || rOldBox.GetLeft() || rOldBox.GetRight() )
638 					{
639 						SvxBoxItem aNew( ATTR_BORDER );
640 						aNew.SetLine( rOldBox.GetLine( BOX_LINE_TOP ), BOX_LINE_LEFT );
641 						aNew.SetLine( rOldBox.GetLine( BOX_LINE_LEFT ), BOX_LINE_TOP );
642 						aNew.SetLine( rOldBox.GetLine( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT );
643 						aNew.SetLine( rOldBox.GetLine( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM );
644 						aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_TOP ), BOX_LINE_LEFT );
645 						aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_LEFT ), BOX_LINE_TOP );
646 						aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT );
647 						aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM );
648 						rNewSet.Put( aNew );
649 					}
650 
651 					const ScMergeAttr& rOldMerge = (const ScMergeAttr&)rSet.Get(ATTR_MERGE);
652 					if (rOldMerge.IsMerged())
653                         rNewSet.Put( ScMergeAttr( Min(
654                                         static_cast<SCsCOL>(rOldMerge.GetRowMerge()),
655                                         static_cast<SCsCOL>(MAXCOL+1 - (nAttrRow2-nRow1))),
656                                     Min(
657                                         static_cast<SCsROW>(rOldMerge.GetColMerge()),
658                                         static_cast<SCsROW>(MAXROW+1 - (nCol-nCol1)))));
659 					const ScMergeFlagAttr& rOldFlag = (const ScMergeFlagAttr&)rSet.Get(ATTR_MERGE_FLAG);
660 					if (rOldFlag.IsOverlapped())
661 					{
662 						sal_Int16 nNewFlags = rOldFlag.GetValue() & ~( SC_MF_HOR | SC_MF_VER );
663 						if ( nNewFlags )
664 							rNewSet.Put( ScMergeFlagAttr( nNewFlags ) );
665 						else
666 							rNewSet.ClearItem( ATTR_MERGE_FLAG );
667 					}
668 
669 					for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
670                         pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1),
671                                 static_cast<SCROW>(nCol-nCol1), aNewPattern, sal_True);
672 				}
673 			}
674 		}
675 
676 		delete pAttrIter;
677 	}
678 }
679 
680 
681 void ScTable::StartAllListeners()
682 {
683 	for (SCCOL i=0; i<=MAXCOL; i++)
684 		aCol[i].StartAllListeners();
685 }
686 
687 
688 void ScTable::StartNeededListeners()
689 {
690 	for (SCCOL i=0; i<=MAXCOL; i++)
691         aCol[i].StartNeededListeners();
692 }
693 
694 
695 void ScTable::BroadcastInArea( SCCOL nCol1, SCROW nRow1,
696 		SCCOL nCol2, SCROW nRow2 )
697 {
698 	if (nCol2 > MAXCOL) nCol2 = MAXCOL;
699 	if (nRow2 > MAXROW) nRow2 = MAXROW;
700 	if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
701 		for (SCCOL i = nCol1; i <= nCol2; i++)
702 			aCol[i].BroadcastInArea( nRow1, nRow2 );
703 }
704 
705 
706 void ScTable::StartListeningInArea( SCCOL nCol1, SCROW nRow1,
707 		SCCOL nCol2, SCROW nRow2 )
708 {
709 	if (nCol2 > MAXCOL) nCol2 = MAXCOL;
710 	if (nRow2 > MAXROW) nRow2 = MAXROW;
711 	if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
712 		for (SCCOL i = nCol1; i <= nCol2; i++)
713 			aCol[i].StartListeningInArea( nRow1, nRow2 );
714 }
715 
716 
717 void ScTable::CopyToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
718 							sal_uInt16 nFlags, sal_Bool bMarked, ScTable* pDestTab,
719 							const ScMarkData* pMarkData,
720 							sal_Bool bAsLink, sal_Bool bColRowFlags)
721 {
722 	if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
723 	{
724 		if (nFlags)
725 			for (SCCOL i = nCol1; i <= nCol2; i++)
726 				aCol[i].CopyToColumn(nRow1, nRow2, nFlags, bMarked,
727 								pDestTab->aCol[i], pMarkData, bAsLink);
728 
729 		if (bColRowFlags)		// Spaltenbreiten/Zeilenhoehen/Flags
730 		{
731 			//	Charts muessen beim Ein-/Ausblenden angepasst werden
732 			ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection();
733 
734             bool bFlagChange = false;
735 
736 			sal_Bool bWidth  = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
737             sal_Bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights);
738 
739 			if (bWidth||bHeight)
740 			{
741 				pDestTab->IncRecalcLevel();
742 
743 				if (bWidth)
744                 {
745 					for (SCCOL i=nCol1; i<=nCol2; i++)
746 					{
747                         bool bThisHidden = ColHidden(i);
748                         bool bHiddenChange = (pDestTab->ColHidden(i) != bThisHidden);
749                         bool bChange = bHiddenChange || (pDestTab->pColWidth[i] != pColWidth[i]);
750 						pDestTab->pColWidth[i] = pColWidth[i];
751 						pDestTab->pColFlags[i] = pColFlags[i];
752                         pDestTab->SetColHidden(i, i, bThisHidden);
753 						//!	Aenderungen zusammenfassen?
754                         if (bHiddenChange && pCharts)
755                             pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, MAXROW, nTab ));
756 
757                         if (bChange)
758                             bFlagChange = true;
759 					}
760                     pDestTab->SetColManualBreaks( maColManualBreaks);
761                 }
762 
763 				if (bHeight)
764 				{
765                     bool bChange = pDestTab->GetRowHeight(nRow1, nRow2) != GetRowHeight(nRow1, nRow2);
766 
767                     if (bChange)
768                         bFlagChange = true;
769 
770                     pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
771                     pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2);
772 
773                     // Hidden flags.
774                     // #i116164# Collect information first, then apply the changes,
775                     // so RowHidden doesn't rebuild the tree for each row range.
776                     std::vector<ScShowRowsEntry> aEntries;
777                     for (SCROW i = nRow1; i <= nRow2; ++i)
778                     {
779                         SCROW nThisLastRow, nDestLastRow;
780                         bool bThisHidden = RowHidden(i, NULL, &nThisLastRow);
781                         bool bDestHidden = pDestTab->RowHidden(i, NULL, &nDestLastRow);
782 
783                         // If the segment sizes differ, we take the shorter segment of the two.
784                         SCROW nLastRow = ::std::min(nThisLastRow, nDestLastRow);
785                         if (nLastRow >= nRow2)
786                             // the last row shouldn't exceed the upper bound the caller specified.
787                             nLastRow = nRow2;
788 
789                         //pDestTab->SetRowHidden(i, nLastRow, bThisHidden);
790                         aEntries.push_back(ScShowRowsEntry(i, nLastRow, !bThisHidden));
791 
792                         bool bThisHiddenChange = (bThisHidden != bDestHidden);
793                         if (bThisHiddenChange && pCharts)
794                         {
795                             // Hidden flags differ.
796                             pCharts->SetRangeDirty(ScRange(0, i, nTab, MAXCOL, nLastRow, nTab));
797                         }
798 
799                         if (bThisHiddenChange)
800                             bFlagChange = true;
801 
802                         // Jump to the last row of the identical flag segment.
803                         i = nLastRow;
804 					}
805 
806                     std::vector<ScShowRowsEntry>::const_iterator aEnd = aEntries.end();
807                     std::vector<ScShowRowsEntry>::const_iterator aIter = aEntries.begin();
808                     if ( aIter != aEnd )
809                     {
810                         pDestTab->mpHiddenRows->setInsertFromBack(true);    // important for undo document
811                         while (aIter != aEnd)
812                         {
813                             pDestTab->SetRowHidden(aIter->mnRow1, aIter->mnRow2, !aIter->mbShow);
814                             ++aIter;
815                         }
816                         pDestTab->mpHiddenRows->setInsertFromBack(false);
817                     }
818 
819                     // Filtered flags.
820                     for (SCROW i = nRow1; i <= nRow2; ++i)
821                     {
822                         SCROW nLastRow;
823                         bool bFiltered = RowFiltered(i, NULL, &nLastRow);
824                         if (nLastRow >= nRow2)
825                             // the last row shouldn't exceed the upper bound the caller specified.
826                             nLastRow = nRow2;
827                         pDestTab->SetRowFiltered(i, nLastRow, bFiltered);
828                         i = nLastRow;
829                     }
830                     pDestTab->SetRowManualBreaks( maRowManualBreaks);
831 				}
832 				pDestTab->DecRecalcLevel();
833 			}
834 
835             if (bFlagChange)
836                 pDestTab->InvalidatePageBreaks();
837 
838 			pDestTab->SetOutlineTable( pOutlineTable );		// auch nur wenn bColRowFlags
839 		}
840 	}
841 }
842 
843 
844 void ScTable::UndoToTable(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
845 							sal_uInt16 nFlags, sal_Bool bMarked, ScTable* pDestTab,
846 							const ScMarkData* pMarkData)
847 {
848 	if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
849 	{
850 		sal_Bool bWidth  = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
851         sal_Bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights);
852 
853 		if (bWidth||bHeight)
854 			IncRecalcLevel();
855 
856 		for ( SCCOL i = 0; i <= MAXCOL; i++)
857 		{
858 			if ( i >= nCol1 && i <= nCol2 )
859 				aCol[i].UndoToColumn(nRow1, nRow2, nFlags, bMarked, pDestTab->aCol[i],
860 										pMarkData);
861 			else
862 				aCol[i].CopyToColumn(0, MAXROW, IDF_FORMULA, sal_False, pDestTab->aCol[i]);
863 		}
864 
865 		if (bWidth||bHeight)
866 		{
867             if (bWidth)
868             {
869                 for (SCCOL i=nCol1; i<=nCol2; i++)
870                     pDestTab->pColWidth[i] = pColWidth[i];
871                 pDestTab->SetColManualBreaks( maColManualBreaks);
872             }
873             if (bHeight)
874             {
875                 pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
876                 pDestTab->SetRowManualBreaks( maRowManualBreaks);
877             }
878             DecRecalcLevel();
879 		}
880 	}
881 }
882 
883 
884 void ScTable::CopyUpdated( const ScTable* pPosTab, ScTable* pDestTab ) const
885 {
886 	for (SCCOL i=0; i<=MAXCOL; i++)
887 		aCol[i].CopyUpdated( pPosTab->aCol[i], pDestTab->aCol[i] );
888 }
889 
890 void ScTable::InvalidateTableArea()
891 {
892     bTableAreaValid = sal_False;
893 }
894 
895 void ScTable::InvalidatePageBreaks()
896 {
897     mbPageBreaksValid = false;
898 }
899 
900 void ScTable::CopyScenarioTo( ScTable* pDestTab ) const
901 {
902 	DBG_ASSERT( bScenario, "bScenario == FALSE" );
903 
904 	for (SCCOL i=0; i<=MAXCOL; i++)
905 		aCol[i].CopyScenarioTo( pDestTab->aCol[i] );
906 }
907 
908 void ScTable::CopyScenarioFrom( const ScTable* pSrcTab )
909 {
910 	DBG_ASSERT( bScenario, "bScenario == FALSE" );
911 
912 	for (SCCOL i=0; i<=MAXCOL; i++)
913 		aCol[i].CopyScenarioFrom( pSrcTab->aCol[i] );
914 }
915 
916 void ScTable::MarkScenarioIn( ScMarkData& rDestMark, sal_uInt16 nNeededBits ) const
917 {
918 	DBG_ASSERT( bScenario, "bScenario == FALSE" );
919 
920 	if ( ( nScenarioFlags & nNeededBits ) != nNeededBits )	// alle Bits gesetzt?
921 		return;
922 
923 	for (SCCOL i=0; i<=MAXCOL; i++)
924 		aCol[i].MarkScenarioIn( rDestMark );
925 }
926 
927 sal_Bool ScTable::HasScenarioRange( const ScRange& rRange ) const
928 {
929 	DBG_ASSERT( bScenario, "bScenario == FALSE" );
930 
931 //	ScMarkData aMark;
932 //	MarkScenarioIn( aMark, 0 );				//! Bits als Parameter von HasScenarioRange?
933 //	return aMark.IsAllMarked( rRange );
934 
935 	ScRange aTabRange = rRange;
936 	aTabRange.aStart.SetTab( nTab );
937 	aTabRange.aEnd.SetTab( nTab );
938 
939 	const ScRangeList* pList = GetScenarioRanges();
940 //	return ( pList && pList->Find( aTabRange ) );
941 
942 	if (pList)
943 	{
944 		sal_uLong nCount = pList->Count();
945 		for ( sal_uLong j = 0; j < nCount; j++ )
946 		{
947 			ScRange* pR = pList->GetObject( j );
948 			if ( pR->Intersects( aTabRange ) )
949 				return sal_True;
950 		}
951 	}
952 
953 	return sal_False;
954 }
955 
956 void ScTable::InvalidateScenarioRanges()
957 {
958 	delete pScenarioRanges;
959 	pScenarioRanges = NULL;
960 }
961 
962 const ScRangeList* ScTable::GetScenarioRanges() const
963 {
964 	DBG_ASSERT( bScenario, "bScenario == FALSE" );
965 
966 	if (!pScenarioRanges)
967 	{
968 		((ScTable*)this)->pScenarioRanges = new ScRangeList;
969 		ScMarkData aMark;
970 		MarkScenarioIn( aMark, 0 );		// immer
971 		aMark.FillRangeListWithMarks( pScenarioRanges, sal_False );
972 	}
973 	return pScenarioRanges;
974 }
975 
976 sal_Bool ScTable::TestCopyScenarioTo( const ScTable* pDestTab ) const
977 {
978 	DBG_ASSERT( bScenario, "bScenario == FALSE" );
979 
980 	if (!pDestTab->IsProtected())
981 		return sal_True;
982 
983 	sal_Bool bOk = sal_True;
984 	for (SCCOL i=0; i<=MAXCOL && bOk; i++)
985 		bOk = aCol[i].TestCopyScenarioTo( pDestTab->aCol[i] );
986 	return bOk;
987 }
988 
989 void ScTable::PutCell( SCCOL nCol, SCROW nRow, ScBaseCell* pCell )
990 {
991 	if (ValidColRow(nCol,nRow))
992 	{
993 		if (pCell)
994 			aCol[nCol].Insert( nRow, pCell );
995 		else
996 			aCol[nCol].Delete( nRow );
997 	}
998 }
999 
1000 
1001 void ScTable::PutCell( SCCOL nCol, SCROW nRow, sal_uLong nFormatIndex, ScBaseCell* pCell )
1002 {
1003 	if (ValidColRow(nCol,nRow))
1004 	{
1005 		if (pCell)
1006 			aCol[nCol].Insert( nRow, nFormatIndex, pCell );
1007 		else
1008 			aCol[nCol].Delete( nRow );
1009 	}
1010 }
1011 
1012 
1013 void ScTable::PutCell( const ScAddress& rPos, ScBaseCell* pCell )
1014 {
1015 	if (pCell)
1016 		aCol[rPos.Col()].Insert( rPos.Row(), pCell );
1017 	else
1018 		aCol[rPos.Col()].Delete( rPos.Row() );
1019 }
1020 
1021 
1022 //UNUSED2009-05 void ScTable::PutCell( const ScAddress& rPos, sal_uLong nFormatIndex, ScBaseCell* pCell )
1023 //UNUSED2009-05 {
1024 //UNUSED2009-05     if (pCell)
1025 //UNUSED2009-05         aCol[rPos.Col()].Insert( rPos.Row(), nFormatIndex, pCell );
1026 //UNUSED2009-05     else
1027 //UNUSED2009-05         aCol[rPos.Col()].Delete( rPos.Row() );
1028 //UNUSED2009-05 }
1029 
1030 
1031 sal_Bool ScTable::SetString( SCCOL nCol, SCROW nRow, SCTAB nTabP, const String& rString,
1032                          SvNumberFormatter* pFormatter, bool bDetectNumberFormat )
1033 {
1034 	if (ValidColRow(nCol,nRow))
1035         return aCol[nCol].SetString(
1036             nRow, nTabP, rString, pDocument->GetAddressConvention(), pFormatter, bDetectNumberFormat );
1037 	else
1038 		return sal_False;
1039 }
1040 
1041 
1042 void ScTable::SetValue( SCCOL nCol, SCROW nRow, const double& rVal )
1043 {
1044 	if (ValidColRow(nCol, nRow))
1045 		aCol[nCol].SetValue( nRow, rVal );
1046 }
1047 
1048 
1049 void ScTable::GetString( SCCOL nCol, SCROW nRow, String& rString )
1050 {
1051 	if (ValidColRow(nCol,nRow))
1052 		aCol[nCol].GetString( nRow, rString );
1053 	else
1054 		rString.Erase();
1055 }
1056 
1057 void  ScTable::FillDPCache( ScDPTableDataCache * pCache, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
1058 {
1059     for ( sal_uInt16 nCol = nStartCol; nCol <= nEndCol; nCol++ )
1060         if( ValidCol( nCol ) )
1061             aCol[nCol].FillDPCache( pCache, nCol - nStartCol, nStartRow, nEndRow );
1062 }
1063 
1064 
1065 void ScTable::GetInputString( SCCOL nCol, SCROW nRow, String& rString )
1066 {
1067 	if (ValidColRow(nCol,nRow))
1068 		aCol[nCol].GetInputString( nRow, rString );
1069 	else
1070 		rString.Erase();
1071 }
1072 
1073 
1074 double ScTable::GetValue( SCCOL nCol, SCROW nRow )
1075 {
1076 	if (ValidColRow( nCol, nRow ))
1077 		return aCol[nCol].GetValue( nRow );
1078 	return 0.0;
1079 }
1080 
1081 
1082 void ScTable::GetFormula( SCCOL nCol, SCROW nRow, String& rFormula,
1083 						  sal_Bool bAsciiExport )
1084 {
1085 	if (ValidColRow(nCol,nRow))
1086 		aCol[nCol].GetFormula( nRow, rFormula, bAsciiExport );
1087 	else
1088 		rFormula.Erase();
1089 }
1090 
1091 
1092 ScPostIt* ScTable::GetNote( SCCOL nCol, SCROW nRow )
1093 {
1094 	return ValidColRow( nCol, nRow ) ? aCol[ nCol ].GetNote( nRow ) : 0;
1095 }
1096 
1097 
1098 void ScTable::TakeNote( SCCOL nCol, SCROW nRow, ScPostIt*& rpNote )
1099 {
1100 	if( ValidColRow( nCol, nRow ) )
1101     {
1102         aCol[ nCol ].TakeNote( nRow, rpNote );
1103         if( rpNote && rpNote->GetNoteData().mxInitData.get() )
1104         {
1105             if( !mxUninitNotes.get() )
1106                 mxUninitNotes.reset( new ScAddress2DVec );
1107             mxUninitNotes->push_back( ScAddress2D( nCol, nRow ) );
1108         }
1109     }
1110     else
1111         DELETEZ( rpNote );
1112 }
1113 
1114 
1115 ScPostIt* ScTable::ReleaseNote( SCCOL nCol, SCROW nRow )
1116 {
1117 	return ValidColRow( nCol, nRow ) ? aCol[ nCol ].ReleaseNote( nRow ) : 0;
1118 }
1119 
1120 
1121 void ScTable::DeleteNote( SCCOL nCol, SCROW nRow )
1122 {
1123 	if( ValidColRow( nCol, nRow ) )
1124         aCol[ nCol ].DeleteNote( nRow );
1125 }
1126 
1127 
1128 void ScTable::InitializeNoteCaptions( bool bForced )
1129 {
1130     if( mxUninitNotes.get() && (bForced || pDocument->IsUndoEnabled()) )
1131     {
1132         for( ScAddress2DVec::iterator aIt = mxUninitNotes->begin(), aEnd = mxUninitNotes->end(); aIt != aEnd; ++aIt )
1133             if( ScPostIt* pNote = GetNote( aIt->first, aIt->second ) )
1134                 pNote->GetOrCreateCaption( ScAddress( aIt->first, aIt->second, nTab ) );
1135         mxUninitNotes.reset();
1136     }
1137 }
1138 
1139 CellType ScTable::GetCellType( SCCOL nCol, SCROW nRow ) const
1140 {
1141 	if (ValidColRow( nCol, nRow ))
1142 		return aCol[nCol].GetCellType( nRow );
1143 	return CELLTYPE_NONE;
1144 }
1145 
1146 
1147 ScBaseCell* ScTable::GetCell( SCCOL nCol, SCROW nRow ) const
1148 {
1149 	if (ValidColRow( nCol, nRow ))
1150 		return aCol[nCol].GetCell( nRow );
1151 
1152 	DBG_ERROR("GetCell ausserhalb");
1153 	return NULL;
1154 }
1155 
1156 void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const
1157 {
1158     rCol = 0;
1159     rRow = MAXROW+1;
1160     while (aCol[rCol].IsEmptyData() && rCol < MAXCOL)
1161         ++rCol;
1162     SCCOL nCol = rCol;
1163     while (nCol <= MAXCOL && rRow > 0)
1164     {
1165         if (!aCol[nCol].IsEmptyData())
1166             rRow = ::std::min( rRow, aCol[nCol].GetFirstDataPos());
1167         ++nCol;
1168     }
1169 }
1170 
1171 void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
1172 {
1173     rCol = MAXCOL;
1174     rRow = 0;
1175     while (aCol[rCol].IsEmptyData() && (rCol > 0))
1176         rCol--;
1177     SCCOL nCol = rCol;
1178     while (nCol >= 0 && rRow < MAXROW)
1179         rRow = ::std::max( rRow, aCol[nCol--].GetLastDataPos());
1180 }
1181 
1182 
1183 sal_Bool ScTable::HasData( SCCOL nCol, SCROW nRow )
1184 {
1185 	if (ValidColRow(nCol,nRow))
1186 		return aCol[nCol].HasDataAt( nRow );
1187 	else
1188 		return sal_False;
1189 }
1190 
1191 
1192 sal_Bool ScTable::HasStringData( SCCOL nCol, SCROW nRow )
1193 {
1194 	if (ValidColRow(nCol,nRow))
1195 		return aCol[nCol].HasStringData( nRow );
1196 	else
1197 		return sal_False;
1198 }
1199 
1200 
1201 sal_Bool ScTable::HasValueData( SCCOL nCol, SCROW nRow )
1202 {
1203 	if (ValidColRow(nCol,nRow))
1204 		return aCol[nCol].HasValueData( nRow );
1205 	else
1206 		return sal_False;
1207 }
1208 
1209 
1210 sal_Bool ScTable::HasStringCells( SCCOL nStartCol, SCROW nStartRow,
1211 								SCCOL nEndCol, SCROW nEndRow ) const
1212 {
1213 	if ( ValidCol(nEndCol) )
1214 		for ( SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++ )
1215 			if (aCol[nCol].HasStringCells(nStartRow, nEndRow))
1216 				return sal_True;
1217 
1218 	return sal_False;
1219 }
1220 
1221 
1222 //UNUSED2008-05  sal_uInt16 ScTable::GetErrCode( SCCOL nCol, SCROW nRow ) const
1223 //UNUSED2008-05  {
1224 //UNUSED2008-05      if (ValidColRow( nCol, nRow ))
1225 //UNUSED2008-05          return aCol[nCol].GetErrCode( nRow );
1226 //UNUSED2008-05      return 0;
1227 //UNUSED2008-05  }
1228 
1229 
1230 void ScTable::SetDirtyVar()
1231 {
1232 	for (SCCOL i=0; i<=MAXCOL; i++)
1233 		aCol[i].SetDirtyVar();
1234 }
1235 
1236 
1237 void ScTable::SetDirty()
1238 {
1239 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1240 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
1241 	for (SCCOL i=0; i<=MAXCOL; i++)
1242 		aCol[i].SetDirty();
1243 	pDocument->SetAutoCalc( bOldAutoCalc );
1244 }
1245 
1246 
1247 void ScTable::SetDirty( const ScRange& rRange )
1248 {
1249 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1250 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
1251 	SCCOL nCol2 = rRange.aEnd.Col();
1252 	for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
1253 		aCol[i].SetDirty( rRange );
1254 	pDocument->SetAutoCalc( bOldAutoCalc );
1255 }
1256 
1257 
1258 void ScTable::SetTableOpDirty( const ScRange& rRange )
1259 {
1260 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1261 	pDocument->SetAutoCalc( sal_False );	// no multiple recalculation
1262 	SCCOL nCol2 = rRange.aEnd.Col();
1263 	for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
1264 		aCol[i].SetTableOpDirty( rRange );
1265 	pDocument->SetAutoCalc( bOldAutoCalc );
1266 }
1267 
1268 
1269 void ScTable::SetDirtyAfterLoad()
1270 {
1271 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1272 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
1273 	for (SCCOL i=0; i<=MAXCOL; i++)
1274 		aCol[i].SetDirtyAfterLoad();
1275 	pDocument->SetAutoCalc( bOldAutoCalc );
1276 }
1277 
1278 
1279 void ScTable::SetRelNameDirty()
1280 {
1281 	sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1282 	pDocument->SetAutoCalc( sal_False );	// Mehrfachberechnungen vermeiden
1283 	for (SCCOL i=0; i<=MAXCOL; i++)
1284 		aCol[i].SetRelNameDirty();
1285 	pDocument->SetAutoCalc( bOldAutoCalc );
1286 }
1287 
1288 
1289 void ScTable::SetLoadingMedium(bool bLoading)
1290 {
1291     mpRowHeights->enableTreeSearch(!bLoading);
1292 
1293     // When loading a medium, prefer inserting row heights from the back
1294     // position since the row heights are stored and read in ascending order
1295     // during import.
1296     mpRowHeights->setInsertFromBack(bLoading);
1297 }
1298 
1299 
1300 void ScTable::CalcAll()
1301 {
1302 	for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CalcAll();
1303 }
1304 
1305 
1306 void ScTable::CompileAll()
1307 {
1308 	for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CompileAll();
1309 }
1310 
1311 
1312 void ScTable::CompileXML( ScProgress& rProgress )
1313 {
1314 	for (SCCOL i=0; i <= MAXCOL; i++)
1315 	{
1316 		aCol[i].CompileXML( rProgress );
1317 	}
1318 }
1319 
1320 void ScTable::CalcAfterLoad()
1321 {
1322 	for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CalcAfterLoad();
1323 }
1324 
1325 
1326 void ScTable::ResetChanged( const ScRange& rRange )
1327 {
1328 	SCCOL nStartCol = rRange.aStart.Col();
1329 	SCROW nStartRow = rRange.aStart.Row();
1330 	SCCOL nEndCol = rRange.aEnd.Col();
1331 	SCROW nEndRow = rRange.aEnd.Row();
1332 
1333 	for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
1334 		aCol[nCol].ResetChanged(nStartRow, nEndRow);
1335 }
1336 
1337 //	Attribute
1338 
1339 const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) const
1340 {
1341 	if (ValidColRow(nCol,nRow))
1342 		return aCol[nCol].GetAttr( nRow, nWhich );
1343 	else
1344 		return NULL;
1345 }
1346 
1347 
1348 sal_uLong ScTable::GetNumberFormat( SCCOL nCol, SCROW nRow ) const
1349 {
1350 	if (ValidColRow(nCol,nRow))
1351 		return aCol[nCol].GetNumberFormat( nRow );
1352 	else
1353 		return 0;
1354 }
1355 
1356 
1357 const ScPatternAttr* ScTable::GetPattern( SCCOL nCol, SCROW nRow ) const
1358 {
1359 	if (ValidColRow(nCol,nRow))
1360 		return aCol[nCol].GetPattern( nRow );
1361 	else
1362     {
1363         DBG_ERROR("wrong column or row");
1364         return pDocument->GetDefPattern();      // for safety
1365     }
1366 }
1367 
1368 
1369 const ScPatternAttr* ScTable::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
1370 {
1371     if ( ValidColRow( nCol, nStartRow ) && ValidRow( nEndRow ) && (nStartRow <= nEndRow) )
1372         return aCol[nCol].GetMostUsedPattern( nStartRow, nEndRow );
1373     else
1374         return NULL;
1375 }
1376 
1377 
1378 bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nMask ) const
1379 {
1380 	bool bFound = false;
1381 	for (SCCOL i=nCol1; i<=nCol2 && !bFound; i++)
1382 		bFound |= aCol[i].HasAttrib( nRow1, nRow2, nMask );
1383 	return bFound;
1384 }
1385 
1386 
1387 //UNUSED2009-05 sal_Bool ScTable::HasLines( const ScRange& rRange, Rectangle& rSizes ) const
1388 //UNUSED2009-05 {
1389 //UNUSED2009-05     SCCOL nCol1 = rRange.aStart.Col();
1390 //UNUSED2009-05     SCROW nRow1 = rRange.aStart.Row();
1391 //UNUSED2009-05     SCCOL nCol2 = rRange.aEnd.Col();
1392 //UNUSED2009-05     SCROW nRow2 = rRange.aEnd.Row();
1393 //UNUSED2009-05     PutInOrder( nCol1, nCol2 );
1394 //UNUSED2009-05     PutInOrder( nRow1, nRow2 );
1395 //UNUSED2009-05
1396 //UNUSED2009-05     sal_Bool bFound = sal_False;
1397 //UNUSED2009-05     for (SCCOL i=nCol1; i<=nCol2; i++)
1398 //UNUSED2009-05         if (aCol[i].HasLines( nRow1, nRow2, rSizes, (i==nCol1), (i==nCol2) ))
1399 //UNUSED2009-05             bFound = sal_True;
1400 //UNUSED2009-05
1401 //UNUSED2009-05     return bFound;
1402 //UNUSED2009-05 }
1403 
1404 
1405 sal_Bool ScTable::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
1406 {
1407 	sal_Bool bFound=sal_False;
1408 	for (SCCOL i=0; i<=MAXCOL && !bFound; i++)
1409 		bFound |= aCol[i].HasAttribSelection( rMark, nMask );
1410 	return bFound;
1411 }
1412 
1413 
1414 sal_Bool ScTable::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
1415 						   SCCOL& rEndCol, SCROW& rEndRow,
1416 						   sal_Bool bRefresh, sal_Bool bAttrs )
1417 {
1418     if (!(ValidCol(nStartCol) && ValidCol(rEndCol)))
1419     {
1420         DBG_ERRORFILE("ScTable::ExtendMerge: invalid column number");
1421         return sal_False;
1422     }
1423 	sal_Bool bFound=sal_False;
1424 	SCCOL nOldEndX = rEndCol;
1425 	SCROW nOldEndY = rEndRow;
1426 	for (SCCOL i=nStartCol; i<=nOldEndX; i++)
1427 		bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh, bAttrs );
1428 	return bFound;
1429 }
1430 
1431 
1432 sal_Bool ScTable::IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bIgnoreNotes ) const
1433 {
1434     if (!(ValidCol(nCol1) && ValidCol(nCol2)))
1435     {
1436         DBG_ERRORFILE("ScTable::IsBlockEmpty: invalid column number");
1437         return sal_False;
1438     }
1439 	sal_Bool bEmpty = sal_True;
1440 	for (SCCOL i=nCol1; i<=nCol2 && bEmpty; i++)
1441 		bEmpty = aCol[i].IsEmptyBlock( nRow1, nRow2, bIgnoreNotes );
1442 	return bEmpty;
1443 }
1444 
1445 SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2,
1446 							SCCOL nCol, SCROW nAttrRow1, SCROW nAttrRow2, SCSIZE nArrY,
1447 							const ScPatternAttr* pPattern, const SfxItemSet* pCondSet )
1448 {
1449 	//	Rueckgabe = neues nArrY
1450 
1451 	sal_uInt8 nRotDir = pPattern->GetRotateDir( pCondSet );
1452 	if ( nRotDir != SC_ROTDIR_NONE )
1453 	{
1454 		sal_Bool bHit = sal_True;
1455 		if ( nCol+1 < nX1 )								// column to the left
1456 			bHit = ( nRotDir != SC_ROTDIR_LEFT );
1457 		else if ( nCol > nX2+1 )						// column to the right
1458 			bHit = ( nRotDir != SC_ROTDIR_RIGHT );		// SC_ROTDIR_STANDARD may now also be extended to the left
1459 
1460 		if ( bHit )
1461 		{
1462 			double nFactor = 0.0;
1463 			if ( nCol > nX2+1 )
1464 			{
1465 				long nRotVal = ((const SfxInt32Item&) pPattern->
1466 						GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue();
1467 				double nRealOrient = nRotVal * F_PI18000;	// 1/100 Grad
1468 				double nCos = cos( nRealOrient );
1469 				double nSin = sin( nRealOrient );
1470 				//!	begrenzen !!!
1471 				//!	zusaetzlich Faktor fuer unterschiedliche PPT X/Y !!!
1472 
1473 				//	bei SC_ROTDIR_LEFT kommt immer ein negativer Wert heraus,
1474 				//	wenn der Modus beruecksichtigt wird
1475 				nFactor = -fabs( nCos / nSin );
1476 			}
1477 
1478 			for ( SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++ )
1479 			{
1480                 if (!RowHidden(nRow))
1481 				{
1482 					sal_Bool bHitOne = sal_True;
1483 					if ( nCol > nX2+1 )
1484 					{
1485 						// reicht die gedrehte Zelle bis in den sichtbaren Bereich?
1486 
1487 						SCCOL nTouchedCol = nCol;
1488                         long nWidth = static_cast<long>(mpRowHeights->getValue(nRow) * nFactor);
1489 						DBG_ASSERT(nWidth <= 0, "Richtung falsch");
1490 						while ( nWidth < 0 && nTouchedCol > 0 )
1491 						{
1492 							--nTouchedCol;
1493 							nWidth += GetColWidth( nTouchedCol );
1494 						}
1495 						if ( nTouchedCol > nX2 )
1496 							bHitOne = sal_False;
1497 					}
1498 
1499 					if (bHitOne)
1500 					{
1501 						while ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo < nRow )
1502 							++nArrY;
1503 						if ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo == nRow )
1504 							pRowInfo[nArrY].nRotMaxCol = nCol;
1505 					}
1506 				}
1507 			}
1508 		}
1509 	}
1510 
1511 	return nArrY;
1512 }
1513 
1514 void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 )
1515 {
1516     if ( !pColWidth || !mpRowHeights || !pColFlags || !pRowFlags )
1517 	{
1518 		DBG_ERROR( "Spalten-/Zeileninfo fehlt" );
1519 		return;
1520 	}
1521 
1522 	//	nRotMaxCol ist auf SC_ROTMAX_NONE initialisiert, nRowNo ist schon gesetzt
1523 
1524 	SCROW nY1 = pRowInfo[0].nRowNo;
1525 	SCROW nY2 = pRowInfo[nArrCount-1].nRowNo;
1526 
1527 	for (SCCOL nCol=0; nCol<=MAXCOL; nCol++)
1528 	{
1529         if (!ColHidden(nCol))
1530 		{
1531 			SCSIZE nArrY = 0;
1532 			ScDocAttrIterator aIter( pDocument, nTab, nCol, nY1, nCol, nY2 );
1533 			SCCOL nAttrCol;
1534             SCROW nAttrRow1, nAttrRow2;
1535 			const ScPatternAttr* pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
1536 			while ( pPattern )
1537 			{
1538 				const SfxPoolItem* pCondItem;
1539 				if ( pPattern->GetItemSet().GetItemState( ATTR_CONDITIONAL, sal_True, &pCondItem )
1540 						== SFX_ITEM_SET )
1541 				{
1542 					//	alle Formate durchgehen, damit die Zellen nicht einzeln
1543 					//	angeschaut werden muessen
1544 
1545 					sal_uLong nIndex = ((const SfxUInt32Item*)pCondItem)->GetValue();
1546 					ScConditionalFormatList* pList = pDocument->GetCondFormList();
1547 					ScStyleSheetPool* pStylePool = pDocument->GetStyleSheetPool();
1548 					if (pList && pStylePool && nIndex)
1549 					{
1550 						const ScConditionalFormat* pFormat = pList->GetFormat(nIndex);
1551 						if ( pFormat )
1552 						{
1553 							sal_uInt16 nEntryCount = pFormat->Count();
1554 							for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++)
1555 							{
1556                                 String aStyleName = pFormat->GetEntry(nEntry)->GetStyle();
1557                                 if (aStyleName.Len())
1558 								{
1559 									SfxStyleSheetBase* pStyleSheet =
1560                                             pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
1561 									if ( pStyleSheet )
1562 									{
1563 										FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
1564 													nCol, nAttrRow1, nAttrRow2,
1565 													nArrY, pPattern, &pStyleSheet->GetItemSet() );
1566 										//	nArrY nicht veraendern
1567 									}
1568 								}
1569 							}
1570 						}
1571 					}
1572 				}
1573 
1574 				nArrY = FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
1575 									nCol, nAttrRow1, nAttrRow2,
1576 									nArrY, pPattern, NULL );
1577 
1578 				pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
1579 			}
1580 		}
1581 	}
1582 }
1583 
1584 sal_Bool ScTable::HasBlockMatrixFragment( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
1585 {
1586 	// nix:0, mitte:1, unten:2, links:4, oben:8, rechts:16, offen:32
1587 	sal_uInt16 nEdges;
1588 
1589 	if ( nCol1 == nCol2 )
1590 	{	// linke und rechte Spalte
1591 		const sal_uInt16 n = 4 | 16;
1592 		nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n );
1593 		// nicht (4 und 16) oder 1 oder 32
1594 		if ( nEdges && (((nEdges & n) != n) || (nEdges & 33)) )
1595 			return sal_True;		// linke oder rechte Kante fehlt oder offen
1596 	}
1597 	else
1598 	{	// linke Spalte
1599 		nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, 4 );
1600 		// nicht 4 oder 1 oder 32
1601 		if ( nEdges && (((nEdges & 4) != 4) || (nEdges & 33)) )
1602 			return sal_True;		// linke Kante fehlt oder offen
1603 		// rechte Spalte
1604 		nEdges = aCol[nCol2].GetBlockMatrixEdges( nRow1, nRow2, 16 );
1605 		// nicht 16 oder 1 oder 32
1606 		if ( nEdges && (((nEdges & 16) != 16) || (nEdges & 33)) )
1607 			return sal_True;		// rechte Kante fehlt oder offen
1608 	}
1609 
1610 	if ( nRow1 == nRow2 )
1611 	{	// obere und untere Zeile
1612 		sal_Bool bOpen = sal_False;
1613 		const sal_uInt16 n = 2 | 8;
1614 		for ( SCCOL i=nCol1; i<=nCol2; i++)
1615 		{
1616 			nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n );
1617 			if ( nEdges )
1618 			{
1619 				if ( (nEdges & n) != n )
1620 					return sal_True;		// obere oder untere Kante fehlt
1621 				if ( nEdges & 4 )
1622 					bOpen = sal_True;		// linke Kante oeffnet, weitersehen
1623 				else if ( !bOpen )
1624 					return sal_True;		// es gibt was, was nicht geoeffnet wurde
1625 				if ( nEdges & 16 )
1626 					bOpen = sal_False;		// rechte Kante schliesst
1627 			}
1628 		}
1629 		if ( bOpen )
1630 			return sal_True;				// es geht noch weiter
1631 	}
1632 	else
1633 	{
1634 		sal_uInt16 j, n;
1635         SCROW nR;
1636 		// erst obere Zeile, dann untere Zeile
1637 		for ( j=0, nR=nRow1, n=8; j<2; j++, nR=nRow2, n=2 )
1638 		{
1639 			sal_Bool bOpen = sal_False;
1640 			for ( SCCOL i=nCol1; i<=nCol2; i++)
1641 			{
1642 				nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n );
1643 				if ( nEdges )
1644 				{
1645 					// in oberere Zeile keine obere Kante bzw.
1646 					// in unterer Zeile keine untere Kante
1647 					if ( (nEdges & n) != n )
1648 						return sal_True;
1649 					if ( nEdges & 4 )
1650 						bOpen = sal_True;		// linke Kante oeffnet, weitersehen
1651 					else if ( !bOpen )
1652 						return sal_True;		// es gibt was, was nicht geoeffnet wurde
1653 					if ( nEdges & 16 )
1654 						bOpen = sal_False;		// rechte Kante schliesst
1655 				}
1656 			}
1657 			if ( bOpen )
1658 				return sal_True;				// es geht noch weiter
1659 		}
1660 	}
1661 	return sal_False;
1662 }
1663 
1664 
1665 sal_Bool ScTable::HasSelectionMatrixFragment( const ScMarkData& rMark ) const
1666 {
1667 	sal_Bool bFound=sal_False;
1668 	for (SCCOL i=0; i<=MAXCOL && !bFound; i++)
1669 		bFound |= aCol[i].HasSelectionMatrixFragment(rMark);
1670 	return bFound;
1671 }
1672 
1673 
1674 sal_Bool ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
1675 			SCROW nRow2, sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
1676 {
1677     if ( !ValidColRow( nCol2, nRow2 ) )
1678     {
1679         DBG_ERRORFILE("IsBlockEditable: invalid column or row");
1680         if (pOnlyNotBecauseOfMatrix)
1681             *pOnlyNotBecauseOfMatrix = sal_False;
1682         return sal_False;
1683     }
1684 
1685 	sal_Bool bIsEditable = sal_True;
1686 	if ( nLockCount )
1687 		bIsEditable = sal_False;
1688     else if ( IsProtected() && !pDocument->IsScenario(nTab) )
1689     {
1690         if((bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED )) != sal_False)
1691         {
1692             // If Sheet is protected and cells are not protected then
1693             // check the active scenario protect flag if this range is
1694             // on the active scenario range. Note the 'copy back' must also
1695             // be set to apply protection.
1696             sal_uInt16 nScenTab = nTab+1;
1697             while(pDocument->IsScenario(nScenTab))
1698             {
1699                 ScRange aEditRange(nCol1, nRow1, nScenTab, nCol2, nRow2, nScenTab);
1700                 if(pDocument->IsActiveScenario(nScenTab) && pDocument->HasScenarioRange(nScenTab, aEditRange))
1701                 {
1702                     sal_uInt16 nFlags;
1703                     pDocument->GetScenarioFlags(nScenTab,nFlags);
1704                     bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY));
1705                     break;
1706                 }
1707                 nScenTab++;
1708             }
1709         }
1710     }
1711     else if (pDocument->IsScenario(nTab))
1712     {
1713         // Determine if the preceding sheet is protected
1714         SCTAB nActualTab = nTab;
1715         do
1716         {
1717             nActualTab--;
1718         }
1719         while(pDocument->IsScenario(nActualTab));
1720 
1721         if(pDocument->IsTabProtected(nActualTab))
1722         {
1723             ScRange aEditRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
1724             if(pDocument->HasScenarioRange(nTab, aEditRange))
1725             {
1726                 sal_uInt16 nFlags;
1727                 pDocument->GetScenarioFlags(nTab,nFlags);
1728                 bIsEditable = !(nFlags & SC_SCENARIO_PROTECT);
1729             }
1730         }
1731     }
1732 	if ( bIsEditable )
1733 	{
1734 		if ( HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2 ) )
1735 		{
1736 			bIsEditable = sal_False;
1737 			if ( pOnlyNotBecauseOfMatrix )
1738 				*pOnlyNotBecauseOfMatrix = sal_True;
1739 		}
1740 		else if ( pOnlyNotBecauseOfMatrix )
1741 			*pOnlyNotBecauseOfMatrix = sal_False;
1742 	}
1743 	else if ( pOnlyNotBecauseOfMatrix )
1744 		*pOnlyNotBecauseOfMatrix = sal_False;
1745 	return bIsEditable;
1746 }
1747 
1748 
1749 sal_Bool ScTable::IsSelectionEditable( const ScMarkData& rMark,
1750 			sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
1751 {
1752 	sal_Bool bIsEditable = sal_True;
1753 	if ( nLockCount )
1754 		bIsEditable = sal_False;
1755     else if ( IsProtected() && !pDocument->IsScenario(nTab) )
1756     {
1757         if((bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED )) != sal_False)
1758         {
1759             // If Sheet is protected and cells are not protected then
1760             // check the active scenario protect flag if this area is
1761             // in the active scenario range.
1762             ScRangeList aRanges;
1763             rMark.FillRangeListWithMarks( &aRanges, sal_False );
1764             sal_uLong nRangeCount = aRanges.Count();
1765             SCTAB nScenTab = nTab+1;
1766             while(pDocument->IsScenario(nScenTab) && bIsEditable)
1767             {
1768                 if(pDocument->IsActiveScenario(nScenTab))
1769                 {
1770                     for (sal_uLong i=0; i<nRangeCount && bIsEditable; i++)
1771                     {
1772                         ScRange aRange = *aRanges.GetObject(i);
1773                         if(pDocument->HasScenarioRange(nScenTab, aRange))
1774                         {
1775                             sal_uInt16 nFlags;
1776                             pDocument->GetScenarioFlags(nScenTab,nFlags);
1777                             bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY));
1778                         }
1779                     }
1780                 }
1781                 nScenTab++;
1782             }
1783         }
1784     }
1785     else if (pDocument->IsScenario(nTab))
1786     {
1787         // Determine if the preceding sheet is protected
1788         SCTAB nActualTab = nTab;
1789         do
1790         {
1791             nActualTab--;
1792         }
1793         while(pDocument->IsScenario(nActualTab));
1794 
1795         if(pDocument->IsTabProtected(nActualTab))
1796         {
1797             ScRangeList aRanges;
1798             rMark.FillRangeListWithMarks( &aRanges, sal_False );
1799             sal_uLong nRangeCount = aRanges.Count();
1800             for (sal_uLong i=0; i<nRangeCount && bIsEditable; i++)
1801             {
1802                 ScRange aRange = *aRanges.GetObject(i);
1803                 if(pDocument->HasScenarioRange(nTab, aRange))
1804                 {
1805                     sal_uInt16 nFlags;
1806                     pDocument->GetScenarioFlags(nTab,nFlags);
1807                     bIsEditable = !(nFlags & SC_SCENARIO_PROTECT);
1808                 }
1809             }
1810         }
1811     }
1812 	if ( bIsEditable )
1813 	{
1814 		if ( HasSelectionMatrixFragment( rMark ) )
1815 		{
1816 			bIsEditable = sal_False;
1817 			if ( pOnlyNotBecauseOfMatrix )
1818 				*pOnlyNotBecauseOfMatrix = sal_True;
1819 		}
1820 		else if ( pOnlyNotBecauseOfMatrix )
1821 			*pOnlyNotBecauseOfMatrix = sal_False;
1822 	}
1823 	else if ( pOnlyNotBecauseOfMatrix )
1824 		*pOnlyNotBecauseOfMatrix = sal_False;
1825 	return bIsEditable;
1826 }
1827 
1828 
1829 
1830 void ScTable::LockTable()
1831 {
1832 	++nLockCount;
1833 }
1834 
1835 
1836 void ScTable::UnlockTable()
1837 {
1838 	if (nLockCount)
1839 		--nLockCount;
1840 	else
1841 	{
1842 		DBG_ERROR("UnlockTable ohne LockTable");
1843 	}
1844 }
1845 
1846 
1847 void ScTable::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, sal_Bool bDeep ) const
1848 {
1849 	for (SCCOL i=0; i<=MAXCOL; i++)
1850 		aCol[i].MergeSelectionPattern( rState, rMark, bDeep );
1851 }
1852 
1853 
1854 void ScTable::MergePatternArea( ScMergePatternState& rState, SCCOL nCol1, SCROW nRow1,
1855 													SCCOL nCol2, SCROW nRow2, sal_Bool bDeep ) const
1856 {
1857 	for (SCCOL i=nCol1; i<=nCol2; i++)
1858 		aCol[i].MergePatternArea( rState, nRow1, nRow2, bDeep );
1859 }
1860 
1861 
1862 void ScTable::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags,
1863 					SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const
1864 {
1865 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1866 	{
1867 		PutInOrder(nStartCol, nEndCol);
1868 		PutInOrder(nStartRow, nEndRow);
1869 		for (SCCOL i=nStartCol; i<=nEndCol; i++)
1870 			aCol[i].MergeBlockFrame( pLineOuter, pLineInner, rFlags,
1871 									nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
1872 	}
1873 }
1874 
1875 
1876 void ScTable::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
1877 					SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
1878 {
1879 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1880 	{
1881 		PutInOrder(nStartCol, nEndCol);
1882 		PutInOrder(nStartRow, nEndRow);
1883 		for (SCCOL i=nStartCol; i<=nEndCol; i++)
1884 			aCol[i].ApplyBlockFrame( pLineOuter, pLineInner,
1885 									nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
1886 	}
1887 }
1888 
1889 
1890 void ScTable::ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
1891 {
1892 	if (ValidColRow(nCol,nRow))
1893 		aCol[nCol].ApplyPattern( nRow, rAttr );
1894 }
1895 
1896 
1897 void ScTable::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1898 									 const ScPatternAttr& rAttr )
1899 {
1900 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1901 	{
1902 		PutInOrder(nStartCol, nEndCol);
1903 		PutInOrder(nStartRow, nEndRow);
1904 		for (SCCOL i = nStartCol; i <= nEndCol; i++)
1905 			aCol[i].ApplyPatternArea(nStartRow, nEndRow, rAttr);
1906 	}
1907 }
1908 
1909 void ScTable::ApplyPooledPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1910 									 const ScPatternAttr& rPooledAttr, const ScPatternAttr& rAttr )
1911 {
1912 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1913 	{
1914 		PutInOrder(nStartCol, nEndCol);
1915 		PutInOrder(nStartRow, nEndRow);
1916 		for (SCCOL i = nStartCol; i <= nEndCol; i++)
1917 		{
1918 			sal_Bool bSet = sal_True;
1919 			SCROW nStar, nEnd;
1920 			const ScPatternAttr* pAttr = aCol[i].GetPatternRange(nStar, nEnd, nStartRow);
1921 			if (nStar >nStartRow || nEnd < nEndRow || pAttr!=pDocument->GetDefPattern())
1922 				bSet = sal_False;
1923 
1924 			if (bSet)
1925 				aCol[i].SetPatternArea(nStartRow, nEndRow, rPooledAttr);
1926 			else
1927 				aCol[i].ApplyPatternArea(nStartRow, nEndRow, rAttr);
1928 		}
1929 	}
1930 }
1931 
1932 void ScTable::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
1933 		const ScPatternAttr& rPattern, short nNewType )
1934 {
1935 	SCCOL nEndCol = rRange.aEnd.Col();
1936 	for ( SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; nCol++ )
1937 	{
1938 		aCol[nCol].ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
1939 	}
1940 }
1941 
1942 
1943 
1944 void ScTable::ApplyStyle( SCCOL nCol, SCROW nRow, const ScStyleSheet& rStyle )
1945 {
1946 	if (ValidColRow(nCol,nRow))
1947 		aCol[nCol].ApplyStyle( nRow, rStyle );
1948 }
1949 
1950 
1951 void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet& rStyle )
1952 {
1953 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1954 	{
1955 		PutInOrder(nStartCol, nEndCol);
1956 		PutInOrder(nStartRow, nEndRow);
1957 		for (SCCOL i = nStartCol; i <= nEndCol; i++)
1958 			aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
1959 	}
1960 }
1961 
1962 
1963 void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
1964 {
1965 	for (SCCOL i=0; i<=MAXCOL; i++)
1966 		aCol[i].ApplySelectionStyle( rStyle, rMark );
1967 }
1968 
1969 
1970 void ScTable::ApplySelectionLineStyle( const ScMarkData& rMark,
1971 							const SvxBorderLine* pLine, sal_Bool bColorOnly )
1972 {
1973 	if ( bColorOnly && !pLine )
1974 		return;
1975 
1976 	for (SCCOL i=0; i<=MAXCOL; i++)
1977 		aCol[i].ApplySelectionLineStyle( rMark, pLine, bColorOnly );
1978 }
1979 
1980 
1981 const ScStyleSheet* ScTable::GetStyle( SCCOL nCol, SCROW nRow ) const
1982 {
1983 	if (ValidColRow(nCol, nRow))
1984 		return aCol[nCol].GetStyle(nRow);
1985 	else
1986 		return NULL;
1987 }
1988 
1989 
1990 const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, sal_Bool& rFound ) const
1991 {
1992 	rFound = sal_False;
1993 
1994 	sal_Bool	bEqual = sal_True;
1995 	sal_Bool	bColFound;
1996 
1997 	const ScStyleSheet* pStyle = NULL;
1998 	const ScStyleSheet* pNewStyle;
1999 
2000 	for (SCCOL i=0; i<=MAXCOL && bEqual; i++)
2001 		if (rMark.HasMultiMarks(i))
2002 		{
2003 			pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound );
2004 			if (bColFound)
2005 			{
2006 				rFound = sal_True;
2007 				if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2008 					bEqual = sal_False;												// unterschiedliche
2009 				pStyle = pNewStyle;
2010 			}
2011 		}
2012 
2013 	return bEqual ? pStyle : NULL;
2014 }
2015 
2016 
2017 const ScStyleSheet*	ScTable::GetAreaStyle( sal_Bool& rFound, SCCOL nCol1, SCROW nRow1,
2018 													SCCOL nCol2, SCROW nRow2 ) const
2019 {
2020 	rFound = sal_False;
2021 
2022 	sal_Bool	bEqual = sal_True;
2023 	sal_Bool	bColFound;
2024 
2025 	const ScStyleSheet* pStyle = NULL;
2026 	const ScStyleSheet* pNewStyle;
2027 
2028 	for (SCCOL i=nCol1; i<=nCol2 && bEqual; i++)
2029 	{
2030 		pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2);
2031 		if (bColFound)
2032 		{
2033 			rFound = sal_True;
2034 			if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2035 				bEqual = sal_False;												// unterschiedliche
2036 			pStyle = pNewStyle;
2037 		}
2038 	}
2039 
2040 	return bEqual ? pStyle : NULL;
2041 }
2042 
2043 
2044 sal_Bool ScTable::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const
2045 {
2046 	sal_Bool bIsUsed = sal_False;
2047 
2048 	for ( SCCOL i=0; i<=MAXCOL; i++ )
2049     {
2050 		if ( aCol[i].IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
2051         {
2052             if ( !bGatherAllStyles )
2053                 return sal_True;
2054             bIsUsed = sal_True;
2055         }
2056     }
2057 
2058 	return bIsUsed;
2059 }
2060 
2061 
2062 void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, sal_Bool bRemoved,
2063 								OutputDevice* pDev,
2064 								double nPPTX, double nPPTY,
2065 								const Fraction& rZoomX, const Fraction& rZoomY )
2066 {
2067     ScFlatBoolRowSegments aUsedRows;
2068     for (SCCOL i = 0; i <= MAXCOL; ++i)
2069         aCol[i].FindStyleSheet(pStyleSheet, aUsedRows, bRemoved);
2070 
2071     SCROW nRow = 0;
2072     while (nRow <= MAXROW)
2073     {
2074         ScFlatBoolRowSegments::RangeData aData;
2075         if (!aUsedRows.getRangeData(nRow, aData))
2076             // search failed!
2077             return;
2078 
2079         SCROW nEndRow = aData.mnRow2;
2080         if (aData.mbValue)
2081             SetOptimalHeight(nRow, nEndRow, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, sal_False);
2082 
2083         nRow = nEndRow + 1;
2084     }
2085 }
2086 
2087 
2088 sal_Bool ScTable::ApplyFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2089 									sal_Int16 nFlags )
2090 {
2091 	sal_Bool bChanged = sal_False;
2092 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2093 		for (SCCOL i = nStartCol; i <= nEndCol; i++)
2094 			bChanged |= aCol[i].ApplyFlags(nStartRow, nEndRow, nFlags);
2095 	return bChanged;
2096 }
2097 
2098 
2099 sal_Bool ScTable::RemoveFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2100 									sal_Int16 nFlags )
2101 {
2102 	sal_Bool bChanged = sal_False;
2103 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2104 		for (SCCOL i = nStartCol; i <= nEndCol; i++)
2105 			bChanged |= aCol[i].RemoveFlags(nStartRow, nEndRow, nFlags);
2106 	return bChanged;
2107 }
2108 
2109 
2110 void ScTable::SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, sal_Bool bPutToPool )
2111 {
2112 	if (ValidColRow(nCol,nRow))
2113 		aCol[nCol].SetPattern( nRow, rAttr, bPutToPool );
2114 }
2115 
2116 
2117 void ScTable::ApplyAttr( SCCOL nCol, SCROW nRow, const SfxPoolItem& rAttr )
2118 {
2119 	if (ValidColRow(nCol,nRow))
2120 		aCol[nCol].ApplyAttr( nRow, rAttr );
2121 }
2122 
2123 
2124 void ScTable::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark )
2125 {
2126 	for (SCCOL i=0; i<=MAXCOL; i++)
2127 		aCol[i].ApplySelectionCache( pCache, rMark );
2128 }
2129 
2130 
2131 void ScTable::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark )
2132 {
2133 	for (SCCOL i=0; i<=MAXCOL; i++)
2134 		aCol[i].ChangeSelectionIndent( bIncrement, rMark );
2135 }
2136 
2137 
2138 void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
2139 {
2140 	for (SCCOL i=0; i<=MAXCOL; i++)
2141 		aCol[i].ClearSelectionItems( pWhich, rMark );
2142 }
2143 
2144 
2145 //	Spaltenbreiten / Zeilenhoehen
2146 
2147 void ScTable::SetColWidth( SCCOL nCol, sal_uInt16 nNewWidth )
2148 {
2149 	if (VALIDCOL(nCol) && pColWidth)
2150 	{
2151 		if (!nNewWidth)
2152 		{
2153 //			DBG_ERROR("Spaltenbreite 0 in SetColWidth");
2154 			nNewWidth = STD_COL_WIDTH;
2155 		}
2156 
2157 		if ( nNewWidth != pColWidth[nCol] )
2158 		{
2159 			IncRecalcLevel();
2160             InitializeNoteCaptions();
2161 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2162 			if (pDrawLayer)
2163 				pDrawLayer->WidthChanged( nTab, nCol, ((long) nNewWidth) - (long) pColWidth[nCol] );
2164 			pColWidth[nCol] = nNewWidth;
2165 			DecRecalcLevel();
2166 
2167             InvalidatePageBreaks();
2168 		}
2169 	}
2170 	else
2171 	{
2172 		DBG_ERROR("Falsche Spaltennummer oder keine Breiten");
2173 	}
2174 }
2175 
2176 
2177 void ScTable::SetRowHeight( SCROW nRow, sal_uInt16 nNewHeight )
2178 {
2179     if (VALIDROW(nRow) && mpRowHeights)
2180 	{
2181 		if (!nNewHeight)
2182 		{
2183 			DBG_ERROR("Zeilenhoehe 0 in SetRowHeight");
2184 			nNewHeight = ScGlobal::nStdRowHeight;
2185 		}
2186 
2187         sal_uInt16 nOldHeight = mpRowHeights->getValue(nRow);
2188 		if ( nNewHeight != nOldHeight )
2189 		{
2190 			IncRecalcLevel();
2191             InitializeNoteCaptions();
2192 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2193 			if (pDrawLayer)
2194 				pDrawLayer->HeightChanged( nTab, nRow, ((long) nNewHeight) - (long) nOldHeight );
2195             mpRowHeights->setValue(nRow, nRow, nNewHeight);
2196 			DecRecalcLevel();
2197 
2198             InvalidatePageBreaks();
2199 		}
2200 	}
2201 	else
2202 	{
2203 		DBG_ERROR("Falsche Zeilennummer oder keine Hoehen");
2204 	}
2205 }
2206 
2207 namespace {
2208 
2209 /**
2210  * Check if the new pixel size is different from the old size between
2211  * specified ranges.
2212  */
2213 bool lcl_pixelSizeChanged(
2214     ScFlatUInt16RowSegments& rRowHeights, SCROW nStartRow, SCROW nEndRow,
2215     sal_uInt16 nNewHeight, double nPPTY)
2216 {
2217     long nNewPix = static_cast<long>(nNewHeight * nPPTY);
2218 
2219     ScFlatUInt16RowSegments::ForwardIterator aFwdIter(rRowHeights);
2220     for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
2221     {
2222         sal_uInt16 nHeight;
2223         if (!aFwdIter.getValue(nRow, nHeight))
2224             break;
2225 
2226         if (nHeight != nNewHeight)
2227         {
2228             bool bChanged = (nNewPix != static_cast<long>(nHeight * nPPTY));
2229             if (bChanged)
2230                 return true;
2231         }
2232 
2233         // Skip ahead to the last position of the current range.
2234         nRow = aFwdIter.getLastPos();
2235     }
2236     return false;
2237 }
2238 
2239 }
2240 
2241 sal_Bool ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight,
2242                                     double /* nPPTX */, double nPPTY )
2243 {
2244 	sal_Bool bChanged = sal_False;
2245     if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights)
2246 	{
2247 		IncRecalcLevel();
2248         InitializeNoteCaptions();
2249 		if (!nNewHeight)
2250 		{
2251 			DBG_ERROR("Zeilenhoehe 0 in SetRowHeight");
2252 			nNewHeight = ScGlobal::nStdRowHeight;
2253 		}
2254 
2255         sal_Bool bSingle = sal_False;   // sal_True = process every row for its own
2256 		ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2257 		if (pDrawLayer)
2258 			if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow ))
2259 				bSingle = sal_True;
2260 
2261 		if (bSingle)
2262 		{
2263             ScFlatUInt16RowSegments::RangeData aData;
2264             mpRowHeights->getRangeData(nStartRow, aData);
2265             if (nNewHeight == aData.mnValue && nEndRow <= aData.mnRow2)
2266                 bSingle = sal_False;    // no difference in this range
2267 		}
2268 		if (bSingle)
2269 		{
2270 			if (nEndRow-nStartRow < 20)
2271             {
2272                 if (!bChanged)
2273                     bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2274 
2275                 /*  #i94028# #i94991# If drawing objects are involved, each row
2276                     has to be changed for its own, because each call to
2277                     ScDrawLayer::HeightChanged expects correct row heights
2278                     above passed row in the document. Cannot use array iterator
2279                     because array changes in every cycle. */
2280                 if( pDrawLayer )
2281                 {
2282                     for( SCROW nRow = nStartRow; nRow <= nEndRow ; ++nRow )
2283                     {
2284                         pDrawLayer->HeightChanged( nTab, nRow,
2285                              static_cast<long>(nNewHeight) - static_cast<long>(mpRowHeights->getValue(nRow)));
2286                         mpRowHeights->setValue(nRow, nRow, nNewHeight);
2287                     }
2288                 }
2289                 else
2290                     mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2291             }
2292 			else
2293 			{
2294 				SCROW nMid = (nStartRow+nEndRow) / 2;
2295 				if (SetRowHeightRange( nStartRow, nMid, nNewHeight, 1.0, 1.0 ))
2296 					bChanged = sal_True;
2297 				if (SetRowHeightRange( nMid+1, nEndRow, nNewHeight, 1.0, 1.0 ))
2298 					bChanged = sal_True;
2299 			}
2300 		}
2301 		else
2302 		{
2303 			if (pDrawLayer)
2304 			{
2305                 // #i115025# When comparing to nNewHeight for the whole range, the height
2306                 // including hidden rows has to be used (same behavior as 3.2).
2307                 unsigned long nOldHeights = mpRowHeights->getSumValue(nStartRow, nEndRow);
2308                 // FIXME: should we test for overflows?
2309 				long nHeightDif = (long) (unsigned long) nNewHeight *
2310                     (nEndRow - nStartRow + 1) - nOldHeights;
2311 				pDrawLayer->HeightChanged( nTab, nEndRow, nHeightDif );
2312 			}
2313 
2314             if (!bChanged)
2315                 bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2316 
2317             mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2318 		}
2319 		DecRecalcLevel();
2320 
2321         if (bChanged)
2322             InvalidatePageBreaks();
2323 	}
2324 	else
2325 	{
2326 		DBG_ERROR("Falsche Zeilennummer oder keine Hoehen");
2327 	}
2328 
2329 	return bChanged;
2330 }
2331 
2332 void ScTable::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight )
2333 {
2334     if (!ValidRow(nStartRow) || !ValidRow(nEndRow) || !mpRowHeights)
2335         return;
2336 
2337     if (!nNewHeight)
2338         nNewHeight = ScGlobal::nStdRowHeight;
2339 
2340     mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2341 }
2342 
2343 void ScTable::SetColWidthOnly( SCCOL nCol, sal_uInt16 nNewWidth )
2344 {
2345 	if (!VALIDCOL(nCol) || !pColWidth)
2346         return;
2347 
2348     if (!nNewWidth)
2349         nNewWidth = STD_COL_WIDTH;
2350 
2351     pColWidth[nCol] = nNewWidth;
2352 }
2353 void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, sal_Bool bManual )
2354 {
2355 	if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags)
2356 	{
2357 		if (bManual)
2358             pRowFlags->OrValue( nStartRow, nEndRow, CR_MANUALSIZE);
2359 		else
2360             pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
2361 	}
2362 	else
2363 	{
2364 		DBG_ERROR("Falsche Zeilennummer oder keine Zeilenflags");
2365 	}
2366 }
2367 
2368 
2369 sal_uInt16 ScTable::GetColWidth( SCCOL nCol ) const
2370 {
2371 	DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
2372 
2373 	if (VALIDCOL(nCol) && pColFlags && pColWidth)
2374 	{
2375         if (ColHidden(nCol))
2376 			return 0;
2377 		else
2378 			return pColWidth[nCol];
2379 	}
2380 	else
2381 		return (sal_uInt16) STD_COL_WIDTH;
2382 }
2383 
2384 
2385 sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const		// immer die eingestellte
2386 {
2387 	DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
2388 
2389 	if (VALIDCOL(nCol) && pColWidth)
2390 		return pColWidth[nCol];
2391 	else
2392 		return (sal_uInt16) STD_COL_WIDTH;
2393 }
2394 
2395 
2396 sal_uInt16 ScTable::GetCommonWidth( SCCOL nEndCol )
2397 {
2398 	//	get the width that is used in the largest continuous column range (up to nEndCol)
2399 
2400 	if ( !ValidCol(nEndCol) )
2401 	{
2402 		DBG_ERROR("wrong column");
2403 		nEndCol = MAXCOL;
2404 	}
2405 
2406 	sal_uInt16 nMaxWidth = 0;
2407 	sal_uInt16 nMaxCount = 0;
2408 	SCCOL nRangeStart = 0;
2409 	while ( nRangeStart <= nEndCol )
2410 	{
2411 		//	skip hidden columns
2412 		while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) )
2413 			++nRangeStart;
2414 		if ( nRangeStart <= nEndCol )
2415 		{
2416 			sal_uInt16 nThisCount = 0;
2417 			sal_uInt16 nThisWidth = pColWidth[nRangeStart];
2418 			SCCOL nRangeEnd = nRangeStart;
2419 			while ( nRangeEnd <= nEndCol && pColWidth[nRangeEnd] == nThisWidth )
2420 			{
2421 				++nThisCount;
2422 				++nRangeEnd;
2423 
2424 				//	skip hidden columns
2425 				while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) )
2426 					++nRangeEnd;
2427 			}
2428 
2429 			if ( nThisCount > nMaxCount )
2430 			{
2431 				nMaxCount = nThisCount;
2432 				nMaxWidth = nThisWidth;
2433 			}
2434 
2435 			nRangeStart = nRangeEnd;		// next range
2436 		}
2437 	}
2438 
2439 	return nMaxWidth;
2440 }
2441 
2442 
2443 sal_uInt16 ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
2444 {
2445     DBG_ASSERT(VALIDROW(nRow),"Invalid row number");
2446 
2447     if (VALIDROW(nRow) && mpRowHeights)
2448     {
2449         if (bHiddenAsZero && RowHidden( nRow, pStartRow, pEndRow))
2450             return 0;
2451         else
2452         {
2453             ScFlatUInt16RowSegments::RangeData aData;
2454             if (!mpRowHeights->getRangeData(nRow, aData))
2455             {
2456                 if (pStartRow)
2457                     *pStartRow = nRow;
2458                 if (pEndRow)
2459                     *pEndRow = nRow;
2460                 // TODO: What should we return in case the search fails?
2461                 return 0;
2462             }
2463 
2464             // If bHiddenAsZero, pStartRow and pEndRow were initialized to
2465             // boundaries of a non-hidden segment. Assume that the previous and
2466             // next segment are hidden then and limit the current height
2467             // segment.
2468             if (pStartRow)
2469                 *pStartRow = (bHiddenAsZero ? std::max( *pStartRow, aData.mnRow1) : aData.mnRow1);
2470             if (pEndRow)
2471                 *pEndRow = (bHiddenAsZero ? std::min( *pEndRow, aData.mnRow2) : aData.mnRow2);
2472             return aData.mnValue;
2473         }
2474     }
2475     else
2476     {
2477         if (pStartRow)
2478             *pStartRow = nRow;
2479         if (pEndRow)
2480             *pEndRow = nRow;
2481         return (sal_uInt16) ScGlobal::nStdRowHeight;
2482     }
2483 }
2484 
2485 
2486 sal_uLong ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow ) const
2487 {
2488 	DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer");
2489 
2490 	if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights)
2491 	{
2492         sal_uLong nHeight = 0;
2493         SCROW nRow = nStartRow;
2494         while (nRow <= nEndRow)
2495         {
2496             SCROW nLastRow = -1;
2497             if (!RowHidden(nRow, nLastRow))
2498             {
2499                 if (nLastRow > nEndRow)
2500                     nLastRow = nEndRow;
2501                 nHeight += mpRowHeights->getSumValue(nRow, nLastRow);
2502             }
2503             nRow = nLastRow + 1;
2504         }
2505         return nHeight;
2506 	}
2507 	else
2508 		return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight);
2509 }
2510 
2511 
2512 sal_uLong ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const
2513 {
2514 	DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer");
2515 
2516 	if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights)
2517 	{
2518         sal_uLong nHeight = 0;
2519         SCROW nRow = nStartRow;
2520         while (nRow <= nEndRow)
2521         {
2522             SCROW nLastRow = -1;
2523             if (!RowHidden(nRow, nLastRow))
2524             {
2525                 if (nLastRow > nEndRow)
2526                     nLastRow = nEndRow;
2527 
2528                 // #i117315# can't use getSumValue, because individual values must be rounded
2529                 while (nRow <= nLastRow)
2530                 {
2531                     ScFlatUInt16RowSegments::RangeData aData;
2532                     if (!mpRowHeights->getRangeData(nRow, aData))
2533                         return nHeight;   // shouldn't happen
2534 
2535                     SCROW nSegmentEnd = std::min( nLastRow, aData.mnRow2 );
2536 
2537                     // round-down a single height value, multiply resulting (pixel) values
2538                     sal_uLong nOneHeight = static_cast<sal_uLong>( aData.mnValue * fScale );
2539                     nHeight += nOneHeight * ( nSegmentEnd + 1 - nRow );
2540 
2541                     nRow = nSegmentEnd + 1;
2542                 }
2543             }
2544             nRow = nLastRow + 1;
2545         }
2546         return nHeight;
2547 	}
2548 	else
2549 		return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight * fScale);
2550 }
2551 
2552 
2553 sal_uInt16 ScTable::GetOriginalHeight( SCROW nRow ) const		// non-0 even if hidden
2554 {
2555 	DBG_ASSERT(VALIDROW(nRow),"wrong row number");
2556 
2557     if (VALIDROW(nRow) && mpRowHeights)
2558         return mpRowHeights->getValue(nRow);
2559 	else
2560 		return (sal_uInt16) ScGlobal::nStdRowHeight;
2561 }
2562 
2563 
2564 //	Spalten-/Zeilen-Flags
2565 
2566 
2567 SCROW ScTable::GetHiddenRowCount( SCROW nRow )
2568 {
2569     if (!ValidRow(nRow))
2570         return 0;
2571 
2572     SCROW nLastRow = -1;
2573     if (!RowHidden(nRow, nLastRow) || !ValidRow(nLastRow))
2574         return 0;
2575 
2576     return nLastRow - nRow + 1;
2577 }
2578 
2579 
2580 //!		ShowRows / DBShowRows zusammenfassen
2581 
2582 void ScTable::ShowCol(SCCOL nCol, bool bShow)
2583 {
2584 	if (VALIDCOL(nCol))
2585 	{
2586         bool bWasVis = !ColHidden(nCol);
2587 		if (bWasVis != bShow)
2588 		{
2589 			IncRecalcLevel();
2590             InitializeNoteCaptions();
2591 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2592 			if (pDrawLayer)
2593 			{
2594 				if (bShow)
2595 					pDrawLayer->WidthChanged( nTab, nCol, (long) pColWidth[nCol] );
2596 				else
2597 					pDrawLayer->WidthChanged( nTab, nCol, -(long) pColWidth[nCol] );
2598 			}
2599 
2600             SetColHidden(nCol, nCol, !bShow);
2601 	    DecRecalcLevel();
2602 
2603 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2604 			if ( pCharts )
2605 				pCharts->SetRangeDirty(ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ));
2606 		}
2607 	}
2608 	else
2609 	{
2610 		DBG_ERROR("Falsche Spaltennummer oder keine Flags");
2611 	}
2612 }
2613 
2614 
2615 void ScTable::ShowRow(SCROW nRow, bool bShow)
2616 {
2617 	if (VALIDROW(nRow) && pRowFlags)
2618 	{
2619         bool bWasVis = !RowHidden(nRow);
2620 		if (bWasVis != bShow)
2621 		{
2622 			IncRecalcLevel();
2623             InitializeNoteCaptions();
2624 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2625 			if (pDrawLayer)
2626 			{
2627 				if (bShow)
2628                     pDrawLayer->HeightChanged(
2629                         nTab, nRow, static_cast<long>(mpRowHeights->getValue(nRow)));
2630 				else
2631                     pDrawLayer->HeightChanged(
2632                         nTab, nRow, -static_cast<long>(mpRowHeights->getValue(nRow)));
2633 			}
2634 
2635             SetRowHidden(nRow, nRow, !bShow);
2636 			if (bShow)
2637                 SetRowFiltered(nRow, nRow, false);
2638 		DecRecalcLevel();
2639 
2640 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2641 			if ( pCharts )
2642 				pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
2643 
2644             InvalidatePageBreaks();
2645 		}
2646 	}
2647 	else
2648 	{
2649 		DBG_ERROR("Falsche Zeilennummer oder keine Flags");
2650 	}
2651 }
2652 
2653 
2654 void ScTable::DBShowRow(SCROW nRow, bool bShow)
2655 {
2656 	if (VALIDROW(nRow) && pRowFlags)
2657 	{
2658         bool bWasVis = !RowHidden(nRow);
2659 		IncRecalcLevel();
2660         InitializeNoteCaptions();
2661 		if (bWasVis != bShow)
2662 		{
2663 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2664 			if (pDrawLayer)
2665 			{
2666 				if (bShow)
2667                     pDrawLayer->HeightChanged(
2668                         nTab, nRow, static_cast<long>(mpRowHeights->getValue(nRow)));
2669 				else
2670                     pDrawLayer->HeightChanged(
2671                         nTab, nRow, -static_cast<long>(mpRowHeights->getValue(nRow)));
2672 			}
2673 		}
2674 
2675 		//	Filter-Flag immer setzen, auch wenn Hidden unveraendert
2676         SetRowHidden(nRow, nRow, !bShow);
2677         SetRowFiltered(nRow, nRow, !bShow);
2678 	DecRecalcLevel();
2679 
2680 		if (bWasVis != bShow)
2681 		{
2682 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2683 			if ( pCharts )
2684 				pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
2685 
2686 			if (pOutlineTable)
2687 				UpdateOutlineRow( nRow, nRow, bShow );
2688 
2689             InvalidatePageBreaks();
2690 		}
2691 	}
2692 	else
2693 	{
2694 		DBG_ERROR("Falsche Zeilennummer oder keine Flags");
2695 	}
2696 }
2697 
2698 
2699 void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow, bool bSetFlags)
2700 {
2701     // #i116164# IncRecalcLevel/DecRecalcLevel is in ScTable::Query
2702 	SCROW nStartRow = nRow1;
2703     InitializeNoteCaptions();
2704 	while (nStartRow <= nRow2)
2705 	{
2706         SCROW nEndRow = -1;
2707         bool bWasVis = !RowHidden(nStartRow, nEndRow);
2708         if (nEndRow > nRow2)
2709             nEndRow = nRow2;
2710 
2711 		sal_Bool bChanged = ( bWasVis != bShow );
2712 		if ( bChanged && bSetFlags )
2713 		{
2714 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2715 			if (pDrawLayer)
2716 			{
2717                 long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow));
2718 				if (bShow)
2719 					pDrawLayer->HeightChanged( nTab, nStartRow, nHeight );
2720 				else
2721 					pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight );
2722 			}
2723 		}
2724 
2725         // #i116164# Directly modify the flags only if there are drawing objects within the area.
2726         // Otherwise, all modifications are made together in ScTable::Query, so the tree isn't constantly rebuilt.
2727         if ( bSetFlags )
2728         {
2729             SetRowHidden(nStartRow, nEndRow, !bShow);
2730             SetRowFiltered(nStartRow, nEndRow, !bShow);
2731         }
2732 
2733 		if ( bChanged )
2734 		{
2735 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2736 			if ( pCharts )
2737 				pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
2738 		}
2739 
2740 		nStartRow = nEndRow + 1;
2741 	}
2742 
2743 	//	#i12341# For Show/Hide rows, the outlines are updated separately from the outside.
2744 	//	For filtering, the changes aren't visible to the caller, so UpdateOutlineRow has
2745 	//	to be done here.
2746 	if (pOutlineTable)
2747 		UpdateOutlineRow( nRow1, nRow2, bShow );
2748 }
2749 
2750 
2751 void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
2752 {
2753 	SCROW nStartRow = nRow1;
2754 	IncRecalcLevel();
2755     InitializeNoteCaptions();
2756 
2757     // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough
2758     ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2759     bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2, false );
2760     long nOldHeight = 0;
2761     if ( pDrawLayer && !bHasObjects )
2762         nOldHeight = static_cast<long>(GetRowHeight(nRow1, nRow2));
2763 
2764 	while (nStartRow <= nRow2)
2765 	{
2766         SCROW nEndRow = -1;
2767         bool bWasVis = !RowHidden(nStartRow, nEndRow);
2768         if (nEndRow > nRow2)
2769             nEndRow = nRow2;
2770 
2771 		sal_Bool bChanged = ( bWasVis != bShow );
2772         if ( bChanged && bHasObjects )
2773 		{
2774 			if (pDrawLayer)
2775 			{
2776                 long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow));
2777 				if (bShow)
2778 					pDrawLayer->HeightChanged( nTab, nStartRow, nHeight );
2779 				else
2780 					pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight );
2781 			}
2782 		}
2783 
2784         // #i116164# Directly modify the flags only if there are drawing objects within the area.
2785         // Otherwise, all rows are modified together after the loop, so the tree isn't constantly rebuilt.
2786         if ( bHasObjects )
2787         {
2788             SetRowHidden(nStartRow, nEndRow, !bShow);
2789             if (bShow)
2790                 SetRowFiltered(nStartRow, nEndRow, false);
2791         }
2792 
2793 		if ( bChanged )
2794 		{
2795 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2796 			if ( pCharts )
2797 				pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
2798 
2799             InvalidatePageBreaks();
2800 		}
2801 
2802 		nStartRow = nEndRow + 1;
2803 	}
2804 
2805     if ( !bHasObjects )
2806     {
2807         // #i116164# set the flags for the whole range at once
2808         SetRowHidden(nRow1, nRow2, !bShow);
2809         if (bShow)
2810             SetRowFiltered(nRow1, nRow2, false);
2811 
2812         if ( pDrawLayer )
2813         {
2814             // if there are no objects in the range, a single HeightChanged call is enough
2815             long nNewHeight = 0;
2816             if ( bShow )
2817                 nNewHeight = static_cast<long>(GetRowHeight(nRow1, nRow2));
2818             if ( nNewHeight != nOldHeight )
2819                 pDrawLayer->HeightChanged( nTab, nRow1, nNewHeight - nOldHeight );
2820         }
2821     }
2822 
2823 	DecRecalcLevel();
2824 }
2825 
2826 sal_Bool ScTable::IsDataFiltered() const
2827 {
2828 	sal_Bool bAnyQuery = sal_False;
2829 	ScDBData* pDBData = pDocument->GetFilterDBAtTable(nTab);
2830 	if ( pDBData )
2831 	{
2832 		ScQueryParam aParam;
2833 		pDBData->GetQueryParam( aParam );
2834 		if ( aParam.GetEntry(0).bDoQuery )
2835 			bAnyQuery = sal_True;
2836 	}
2837 	return bAnyQuery;
2838 }
2839 
2840 void ScTable::SetColFlags( SCCOL nCol, sal_uInt8 nNewFlags )
2841 {
2842 	if (VALIDCOL(nCol) && pColFlags)
2843 		pColFlags[nCol] = nNewFlags;
2844 	else
2845 	{
2846 		DBG_ERROR("Falsche Spaltennummer oder keine Flags");
2847 	}
2848 }
2849 
2850 
2851 void ScTable::SetRowFlags( SCROW nRow, sal_uInt8 nNewFlags )
2852 {
2853 	if (VALIDROW(nRow) && pRowFlags)
2854 		pRowFlags->SetValue( nRow, nNewFlags);
2855 	else
2856 	{
2857 		DBG_ERROR("Falsche Zeilennummer oder keine Flags");
2858 	}
2859 }
2860 
2861 
2862 void ScTable::SetRowFlags( SCROW nStartRow, SCROW nEndRow, sal_uInt8 nNewFlags )
2863 {
2864 	if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags)
2865 		pRowFlags->SetValue( nStartRow, nEndRow, nNewFlags);
2866 	else
2867 	{
2868 		DBG_ERROR("Falsche Zeilennummer(n) oder keine Flags");
2869 	}
2870 }
2871 
2872 
2873 sal_uInt8 ScTable::GetColFlags( SCCOL nCol ) const
2874 {
2875 	if (VALIDCOL(nCol) && pColFlags)
2876 		return pColFlags[nCol];
2877 	else
2878 		return 0;
2879 }
2880 
2881 
2882 sal_uInt8 ScTable::GetRowFlags( SCROW nRow ) const
2883 {
2884 	if (VALIDROW(nRow) && pRowFlags)
2885 		return pRowFlags->GetValue(nRow);
2886 	else
2887 		return 0;
2888 }
2889 
2890 
2891 SCROW ScTable::GetLastFlaggedRow() const
2892 {
2893     SCROW nLastFound = 0;
2894     if (pRowFlags)
2895     {
2896         SCROW nRow = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<sal_uInt8>(CR_ALL) );
2897         if (ValidRow(nRow))
2898             nLastFound = nRow;
2899     }
2900 
2901     if (!maRowManualBreaks.empty())
2902         nLastFound = ::std::max(nLastFound, *maRowManualBreaks.rbegin());
2903 
2904     if (mpHiddenRows)
2905     {
2906         SCROW nRow = mpHiddenRows->findLastNotOf(false);
2907         if (ValidRow(nRow))
2908             nLastFound = ::std::max(nLastFound, nRow);
2909     }
2910 
2911     if (mpFilteredRows)
2912     {
2913         SCROW nRow = mpFilteredRows->findLastNotOf(false);
2914         if (ValidRow(nRow))
2915             nLastFound = ::std::max(nLastFound, nRow);
2916     }
2917 
2918     return nLastFound;
2919 }
2920 
2921 
2922 SCCOL ScTable::GetLastChangedCol() const
2923 {
2924 	if ( !pColFlags )
2925 		return 0;
2926 
2927 	SCCOL nLastFound = 0;
2928 	for (SCCOL nCol = 1; nCol <= MAXCOL; nCol++)
2929         if ((pColFlags[nCol] & CR_ALL) || (pColWidth[nCol] != STD_COL_WIDTH))
2930 			nLastFound = nCol;
2931 
2932 	return nLastFound;
2933 }
2934 
2935 
2936 SCROW ScTable::GetLastChangedRow() const
2937 {
2938 	if ( !pRowFlags )
2939 		return 0;
2940 
2941     SCROW nLastFlags = GetLastFlaggedRow();
2942 
2943     // Find the last row position where the height is NOT the standard row
2944     // height.
2945     // KOHEI: Test this to make sure it does what it's supposed to.
2946     SCROW nLastHeight = mpRowHeights->findLastNotOf(ScGlobal::nStdRowHeight);
2947     if (!ValidRow(nLastHeight))
2948         nLastHeight = 0;
2949 
2950 	return std::max( nLastFlags, nLastHeight);
2951 }
2952 
2953 
2954 sal_Bool ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, sal_Bool bShow )
2955 {
2956 	if (pOutlineTable && pColFlags)
2957     {
2958         ScBitMaskCompressedArray< SCCOLROW, sal_uInt8> aArray( MAXCOL, pColFlags, MAXCOLCOUNT);
2959 		return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, *this, true );
2960     }
2961 	else
2962 		return sal_False;
2963 }
2964 
2965 
2966 sal_Bool ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, sal_Bool bShow )
2967 {
2968 	if (pOutlineTable && pRowFlags)
2969 		return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, *this, false );
2970 	else
2971 		return sal_False;
2972 }
2973 
2974 
2975 void ScTable::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
2976 {
2977     // Column-wise expansion
2978 
2979     while (rX1 > 0 && ColHidden(rX1-1))
2980         --rX1;
2981 
2982     while (rX2 < MAXCOL && ColHidden(rX2+1))
2983         ++rX2;
2984 
2985     // Row-wise expansion
2986 
2987     if (rY1 > 0)
2988 	{
2989         ScFlatBoolRowSegments::RangeData aData;
2990         if (mpHiddenRows->getRangeData(rY1-1, aData) && aData.mbValue)
2991         {
2992             SCROW nStartRow = aData.mnRow1;
2993             if (ValidRow(nStartRow))
2994                 rY1 = nStartRow;
2995         }
2996     }
2997     if (rY2 < MAXROW)
2998     {
2999         SCROW nEndRow = -1;
3000         if (RowHidden(rY2+1, nEndRow) && ValidRow(nEndRow))
3001             rY2 = nEndRow;
3002 	}
3003 }
3004 
3005 
3006 void ScTable::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
3007 {
3008     while ( rX2>rX1 && ColHidden(rX2) )
3009         --rX2;
3010     while ( rX2>rX1 && ColHidden(rX1) )
3011         ++rX1;
3012 
3013     if (rY1 < rY2)
3014 	{
3015         ScFlatBoolRowSegments::RangeData aData;
3016         if (mpHiddenRows->getRangeData(rY2, aData) && aData.mbValue)
3017         {
3018             SCROW nStartRow = aData.mnRow1;
3019             if (ValidRow(nStartRow) && nStartRow >= rY1)
3020                 rY2 = nStartRow;
3021         }
3022     }
3023 
3024     if (rY1 < rY2)
3025     {
3026         SCROW nEndRow = -1;
3027         if (RowHidden(rY1, nEndRow) && ValidRow(nEndRow) && nEndRow <= rY2)
3028             rY1 = nEndRow;
3029 	}
3030 }
3031 
3032 
3033 //	Auto-Outline
3034 
3035 template< typename T >
3036 short DiffSign( T a, T b )
3037 {
3038 	return (a<b) ? -1 :
3039 			(a>b) ? 1 : 0;
3040 }
3041 
3042 
3043 void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
3044 {
3045 	sal_Bool bSizeChanged = sal_False;
3046 	sal_Bool bMissed	  = sal_False;
3047 
3048 	SCCOL nCol;
3049 	SCROW nRow;
3050 	SCROW i;
3051 	sal_Bool bFound;
3052 	ScOutlineArray* pArray;
3053 	ScBaseCell* pCell;
3054 	ScRange aRef;
3055 /*	ScPatternAttr aBoldPattern( pDocument->GetPool() );				//!	spezielle Format-Vorlage
3056 	aBoldPattern.GetItemSet().Put( SvxWeightItem( WEIGHT_BOLD ) );
3057 */
3058 
3059 	StartOutlineTable();
3060 
3061 							// Zeilen
3062 
3063 	SCROW	nCount = nEndRow-nStartRow+1;
3064 	sal_Bool*	pUsed = new sal_Bool[nCount];
3065 	for (i=0; i<nCount; i++)
3066 		pUsed[i] = sal_False;
3067 	for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3068 		if (!aCol[nCol].IsEmptyData())
3069 			aCol[nCol].FindUsed( nStartRow, nEndRow, pUsed );
3070 
3071 	pArray = pOutlineTable->GetRowArray();
3072 	for (nRow=nStartRow; nRow<=nEndRow; nRow++)
3073 		if (pUsed[nRow-nStartRow])
3074 		{
3075 			bFound = sal_False;
3076 			for (nCol=nStartCol; nCol<=nEndCol && !bFound; nCol++)
3077 				if (!aCol[nCol].IsEmptyData())
3078 				{
3079 					pCell = aCol[nCol].GetCell( nRow );
3080 					if (pCell)
3081 						if ( pCell->GetCellType() == CELLTYPE_FORMULA )
3082 							if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
3083 								if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
3084 									 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
3085 									 DiffSign( aRef.aStart.Row(), nRow ) ==
3086 										DiffSign( aRef.aEnd.Row(), nRow ) )
3087 								{
3088 									if (pArray->Insert( aRef.aStart.Row(), aRef.aEnd.Row(), bSizeChanged ))
3089 									{
3090 //										ApplyPatternArea( nStartCol, nRow, nEndCol, nRow, aBoldPattern );
3091 										bFound = sal_True;
3092 									}
3093 									else
3094 										bMissed = sal_True;
3095 								}
3096 				}
3097 		}
3098 
3099 	delete[] pUsed;
3100 
3101 							// Spalten
3102 
3103 	pArray = pOutlineTable->GetColArray();
3104 	for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3105 	{
3106 		if (!aCol[nCol].IsEmptyData())
3107 		{
3108 			bFound = sal_False;
3109 			ScColumnIterator aIter( &aCol[nCol], nStartRow, nEndRow );
3110 			while ( aIter.Next( nRow, pCell ) && !bFound )
3111 			{
3112 				if ( pCell->GetCellType() == CELLTYPE_FORMULA )
3113 					if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
3114 						if ( aRef.aStart.Row() == nRow && aRef.aEnd.Row() == nRow &&
3115 							 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
3116 							 DiffSign( aRef.aStart.Col(), nCol ) ==
3117 								DiffSign( aRef.aEnd.Col(), nCol ) )
3118 						{
3119 							if (pArray->Insert( aRef.aStart.Col(), aRef.aEnd.Col(), bSizeChanged ))
3120 							{
3121 //								ApplyPatternArea( nCol, nStartRow, nCol, nEndRow, aBoldPattern );
3122 								bFound = sal_True;
3123 							}
3124 							else
3125 								bMissed = sal_True;
3126 						}
3127 			}
3128 		}
3129 	}
3130 }
3131 
3132 									//	CopyData - fuer Query in anderen Bereich
3133 
3134 void ScTable::CopyData( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
3135 							SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab )
3136 {
3137 	//!		wenn fuer mehrere Zeilen benutzt, nach Spalten optimieren!
3138 
3139 	ScAddress aSrc( nStartCol, nStartRow, nTab );
3140 	ScAddress aDest( nDestCol, nDestRow, nDestTab );
3141 	ScRange aRange( aSrc, aDest );
3142 	sal_Bool bThisTab = ( nDestTab == nTab );
3143 	SCROW nDestY = nDestRow;
3144 	for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
3145 	{
3146 		aSrc.SetRow( nRow );
3147 		aDest.SetRow( nDestY );
3148 		SCCOL nDestX = nDestCol;
3149 		for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
3150 		{
3151 			aSrc.SetCol( nCol );
3152 			aDest.SetCol( nDestX );
3153 			ScBaseCell* pCell = GetCell( nCol, nRow );
3154 			if (pCell)
3155 			{
3156                 pCell = pCell->CloneWithoutNote( *pDocument );
3157 				if (pCell->GetCellType() == CELLTYPE_FORMULA)
3158 				{
3159 					((ScFormulaCell*)pCell)->UpdateReference( URM_COPY, aRange,
3160 									((SCsCOL) nDestCol) - ((SCsCOL) nStartCol),
3161 									((SCsROW) nDestRow) - ((SCsROW) nStartRow),
3162 									((SCsTAB) nDestTab) - ((SCsTAB) nTab) );
3163 					((ScFormulaCell*)pCell)->aPos = aDest;
3164 				}
3165 			}
3166 			if (bThisTab)
3167 			{
3168 				PutCell( nDestX, nDestY, pCell );
3169 				SetPattern( nDestX, nDestY, *GetPattern( nCol, nRow ), sal_True );
3170 			}
3171 			else
3172 			{
3173 				pDocument->PutCell( aDest, pCell );
3174 				pDocument->SetPattern( aDest, *GetPattern( nCol, nRow ), sal_True );
3175 			}
3176 
3177 			++nDestX;
3178 		}
3179 		++nDestY;
3180 	}
3181 }
3182 
3183 
3184 sal_Bool ScTable::RefVisible(ScFormulaCell* pCell)
3185 {
3186 	ScRange aRef;
3187 
3188 	if (pCell->HasOneReference(aRef))
3189 	{
3190 		if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab())
3191 		{
3192             SCROW nEndRow;
3193             if (!RowFiltered(aRef.aStart.Row(), NULL, &nEndRow))
3194                 // row not filtered.
3195                 nEndRow = ::std::numeric_limits<SCROW>::max();
3196 
3197             if (!ValidRow(nEndRow) || nEndRow < aRef.aEnd.Row())
3198                 return sal_True;    // at least partly visible
3199             return sal_False;       // completely invisible
3200 		}
3201 	}
3202 
3203 	return sal_True;						// irgendwie anders
3204 }
3205 
3206 
3207 void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, String& rStr)
3208 {
3209 	GetInputString(nCol, nRow, rStr);
3210 	rStr.EraseTrailingChars();
3211 	rStr.EraseLeadingChars();
3212 	ScGlobal::pCharClass->toUpper(rStr);
3213 }
3214 
3215 
3216 // Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage
3217 
3218 void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos)
3219 {
3220 	ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
3221 	if( pDrawLayer )
3222 	{
3223         double fValX = GetColOffset( MAXCOL + 1 ) * HMM_PER_TWIPS;
3224         double fValY = GetRowOffset( MAXROW + 1 ) * HMM_PER_TWIPS;
3225         const long nMax = ::std::numeric_limits<long>::max();
3226         // #i113884# Avoid int32 overflow with possible negative results than can cause bad effects.
3227         // If the draw page size is smaller than all rows, only the bottom of the sheet is affected.
3228         long x = ( fValX > (double)nMax ) ? nMax : (long) fValX;
3229         long y = ( fValY > (double)nMax ) ? nMax : (long) fValY;
3230 
3231 		if ( IsLayoutRTL() )		// IsNegativePage
3232 			x = -x;
3233 
3234 		pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( x, y ), bUpdateNoteCaptionPos );
3235 	}
3236 
3237     // #i102616# actions that modify the draw page size count as sheet modification
3238     // (exception: InitDrawLayer)
3239     if (bResetStreamValid && IsStreamValid())
3240         SetStreamValid(sal_False);
3241 }
3242 
3243 
3244 sal_uLong ScTable::GetRowOffset( SCROW nRow ) const
3245 {
3246 	sal_uLong n = 0;
3247     if ( mpHiddenRows && mpRowHeights )
3248 	{
3249         if (nRow == 0)
3250             return 0;
3251         else if (nRow == 1)
3252             return GetRowHeight(0);
3253 
3254         n = GetTotalRowHeight(0, nRow-1);
3255 #ifdef DBG_UTIL
3256         if (n == ::std::numeric_limits<unsigned long>::max())
3257             DBG_ERRORFILE("ScTable::GetRowOffset: row heights overflow");
3258 #endif
3259 	}
3260 	else
3261 	{
3262 		DBG_ERROR("GetRowOffset: Daten fehlen");
3263 	}
3264 	return n;
3265 }
3266 
3267 SCROW ScTable::GetRowForHeight(sal_uLong nHeight) const
3268 {
3269     sal_uInt32 nSum = 0;
3270 
3271     ScFlatBoolRowSegments::RangeData aData;
3272     for (SCROW nRow = 0; nRow <= MAXROW; ++nRow)
3273     {
3274         if (!mpHiddenRows->getRangeData(nRow, aData))
3275             break;
3276 
3277         if (aData.mbValue)
3278         {
3279             nRow = aData.mnRow2;
3280             continue;
3281         }
3282 
3283         sal_uInt32 nNew = mpRowHeights->getValue(nRow);
3284         nSum += nNew;
3285         if (nSum > nHeight)
3286         {
3287             return nRow < MAXROW ? nRow + 1 : MAXROW;
3288         }
3289     }
3290     return -1;
3291 }
3292 
3293 
3294 sal_uLong ScTable::GetColOffset( SCCOL nCol ) const
3295 {
3296 	sal_uLong n = 0;
3297 	if ( pColWidth )
3298 	{
3299 		SCCOL i;
3300 		for( i = 0; i < nCol; i++ )
3301             if (!ColHidden(i))
3302 				n += pColWidth[i];
3303 	}
3304 	else
3305 	{
3306 		DBG_ERROR("GetColumnOffset: Daten fehlen");
3307 	}
3308 	return n;
3309 }
3310 
3311 ScColumn* ScTable::GetColumnByIndex(sal_Int32 index)
3312 {
3313 	if( index <= MAXCOL && index >= 0 )
3314 	{
3315 		return &(aCol[index]);
3316 	}
3317 	return NULL;
3318 }
3319 
3320