xref: /aoo41x/main/sc/source/core/data/table2.cxx (revision b4df81e3)
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::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
1910 		const ScPatternAttr& rPattern, short nNewType )
1911 {
1912 	SCCOL nEndCol = rRange.aEnd.Col();
1913 	for ( SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; nCol++ )
1914 	{
1915 		aCol[nCol].ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
1916 	}
1917 }
1918 
1919 
1920 
1921 void ScTable::ApplyStyle( SCCOL nCol, SCROW nRow, const ScStyleSheet& rStyle )
1922 {
1923 	if (ValidColRow(nCol,nRow))
1924 		aCol[nCol].ApplyStyle( nRow, rStyle );
1925 }
1926 
1927 
1928 void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet& rStyle )
1929 {
1930 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1931 	{
1932 		PutInOrder(nStartCol, nEndCol);
1933 		PutInOrder(nStartRow, nEndRow);
1934 		for (SCCOL i = nStartCol; i <= nEndCol; i++)
1935 			aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
1936 	}
1937 }
1938 
1939 
1940 void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
1941 {
1942 	for (SCCOL i=0; i<=MAXCOL; i++)
1943 		aCol[i].ApplySelectionStyle( rStyle, rMark );
1944 }
1945 
1946 
1947 void ScTable::ApplySelectionLineStyle( const ScMarkData& rMark,
1948 							const SvxBorderLine* pLine, sal_Bool bColorOnly )
1949 {
1950 	if ( bColorOnly && !pLine )
1951 		return;
1952 
1953 	for (SCCOL i=0; i<=MAXCOL; i++)
1954 		aCol[i].ApplySelectionLineStyle( rMark, pLine, bColorOnly );
1955 }
1956 
1957 
1958 const ScStyleSheet* ScTable::GetStyle( SCCOL nCol, SCROW nRow ) const
1959 {
1960 	if (ValidColRow(nCol, nRow))
1961 		return aCol[nCol].GetStyle(nRow);
1962 	else
1963 		return NULL;
1964 }
1965 
1966 
1967 const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, sal_Bool& rFound ) const
1968 {
1969 	rFound = sal_False;
1970 
1971 	sal_Bool	bEqual = sal_True;
1972 	sal_Bool	bColFound;
1973 
1974 	const ScStyleSheet* pStyle = NULL;
1975 	const ScStyleSheet* pNewStyle;
1976 
1977 	for (SCCOL i=0; i<=MAXCOL && bEqual; i++)
1978 		if (rMark.HasMultiMarks(i))
1979 		{
1980 			pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound );
1981 			if (bColFound)
1982 			{
1983 				rFound = sal_True;
1984 				if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
1985 					bEqual = sal_False;												// unterschiedliche
1986 				pStyle = pNewStyle;
1987 			}
1988 		}
1989 
1990 	return bEqual ? pStyle : NULL;
1991 }
1992 
1993 
1994 const ScStyleSheet*	ScTable::GetAreaStyle( sal_Bool& rFound, SCCOL nCol1, SCROW nRow1,
1995 													SCCOL nCol2, SCROW nRow2 ) const
1996 {
1997 	rFound = sal_False;
1998 
1999 	sal_Bool	bEqual = sal_True;
2000 	sal_Bool	bColFound;
2001 
2002 	const ScStyleSheet* pStyle = NULL;
2003 	const ScStyleSheet* pNewStyle;
2004 
2005 	for (SCCOL i=nCol1; i<=nCol2 && bEqual; i++)
2006 	{
2007 		pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2);
2008 		if (bColFound)
2009 		{
2010 			rFound = sal_True;
2011 			if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2012 				bEqual = sal_False;												// unterschiedliche
2013 			pStyle = pNewStyle;
2014 		}
2015 	}
2016 
2017 	return bEqual ? pStyle : NULL;
2018 }
2019 
2020 
2021 sal_Bool ScTable::IsStyleSheetUsed( const ScStyleSheet& rStyle, sal_Bool bGatherAllStyles ) const
2022 {
2023 	sal_Bool bIsUsed = sal_False;
2024 
2025 	for ( SCCOL i=0; i<=MAXCOL; i++ )
2026     {
2027 		if ( aCol[i].IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
2028         {
2029             if ( !bGatherAllStyles )
2030                 return sal_True;
2031             bIsUsed = sal_True;
2032         }
2033     }
2034 
2035 	return bIsUsed;
2036 }
2037 
2038 
2039 void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, sal_Bool bRemoved,
2040 								OutputDevice* pDev,
2041 								double nPPTX, double nPPTY,
2042 								const Fraction& rZoomX, const Fraction& rZoomY )
2043 {
2044     ScFlatBoolRowSegments aUsedRows;
2045     for (SCCOL i = 0; i <= MAXCOL; ++i)
2046         aCol[i].FindStyleSheet(pStyleSheet, aUsedRows, bRemoved);
2047 
2048     SCROW nRow = 0;
2049     while (nRow <= MAXROW)
2050     {
2051         ScFlatBoolRowSegments::RangeData aData;
2052         if (!aUsedRows.getRangeData(nRow, aData))
2053             // search failed!
2054             return;
2055 
2056         SCROW nEndRow = aData.mnRow2;
2057         if (aData.mbValue)
2058             SetOptimalHeight(nRow, nEndRow, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, sal_False);
2059 
2060         nRow = nEndRow + 1;
2061     }
2062 }
2063 
2064 
2065 sal_Bool ScTable::ApplyFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2066 									sal_Int16 nFlags )
2067 {
2068 	sal_Bool bChanged = sal_False;
2069 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2070 		for (SCCOL i = nStartCol; i <= nEndCol; i++)
2071 			bChanged |= aCol[i].ApplyFlags(nStartRow, nEndRow, nFlags);
2072 	return bChanged;
2073 }
2074 
2075 
2076 sal_Bool ScTable::RemoveFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2077 									sal_Int16 nFlags )
2078 {
2079 	sal_Bool bChanged = sal_False;
2080 	if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2081 		for (SCCOL i = nStartCol; i <= nEndCol; i++)
2082 			bChanged |= aCol[i].RemoveFlags(nStartRow, nEndRow, nFlags);
2083 	return bChanged;
2084 }
2085 
2086 
2087 void ScTable::SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, sal_Bool bPutToPool )
2088 {
2089 	if (ValidColRow(nCol,nRow))
2090 		aCol[nCol].SetPattern( nRow, rAttr, bPutToPool );
2091 }
2092 
2093 
2094 void ScTable::ApplyAttr( SCCOL nCol, SCROW nRow, const SfxPoolItem& rAttr )
2095 {
2096 	if (ValidColRow(nCol,nRow))
2097 		aCol[nCol].ApplyAttr( nRow, rAttr );
2098 }
2099 
2100 
2101 void ScTable::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark )
2102 {
2103 	for (SCCOL i=0; i<=MAXCOL; i++)
2104 		aCol[i].ApplySelectionCache( pCache, rMark );
2105 }
2106 
2107 
2108 void ScTable::ChangeSelectionIndent( sal_Bool bIncrement, const ScMarkData& rMark )
2109 {
2110 	for (SCCOL i=0; i<=MAXCOL; i++)
2111 		aCol[i].ChangeSelectionIndent( bIncrement, rMark );
2112 }
2113 
2114 
2115 void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
2116 {
2117 	for (SCCOL i=0; i<=MAXCOL; i++)
2118 		aCol[i].ClearSelectionItems( pWhich, rMark );
2119 }
2120 
2121 
2122 //	Spaltenbreiten / Zeilenhoehen
2123 
2124 void ScTable::SetColWidth( SCCOL nCol, sal_uInt16 nNewWidth )
2125 {
2126 	if (VALIDCOL(nCol) && pColWidth)
2127 	{
2128 		if (!nNewWidth)
2129 		{
2130 //			DBG_ERROR("Spaltenbreite 0 in SetColWidth");
2131 			nNewWidth = STD_COL_WIDTH;
2132 		}
2133 
2134 		if ( nNewWidth != pColWidth[nCol] )
2135 		{
2136 			IncRecalcLevel();
2137             InitializeNoteCaptions();
2138 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2139 			if (pDrawLayer)
2140 				pDrawLayer->WidthChanged( nTab, nCol, ((long) nNewWidth) - (long) pColWidth[nCol] );
2141 			pColWidth[nCol] = nNewWidth;
2142 			DecRecalcLevel();
2143 
2144             InvalidatePageBreaks();
2145 		}
2146 	}
2147 	else
2148 	{
2149 		DBG_ERROR("Falsche Spaltennummer oder keine Breiten");
2150 	}
2151 }
2152 
2153 
2154 void ScTable::SetRowHeight( SCROW nRow, sal_uInt16 nNewHeight )
2155 {
2156     if (VALIDROW(nRow) && mpRowHeights)
2157 	{
2158 		if (!nNewHeight)
2159 		{
2160 			DBG_ERROR("Zeilenhoehe 0 in SetRowHeight");
2161 			nNewHeight = ScGlobal::nStdRowHeight;
2162 		}
2163 
2164         sal_uInt16 nOldHeight = mpRowHeights->getValue(nRow);
2165 		if ( nNewHeight != nOldHeight )
2166 		{
2167 			IncRecalcLevel();
2168             InitializeNoteCaptions();
2169 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2170 			if (pDrawLayer)
2171 				pDrawLayer->HeightChanged( nTab, nRow, ((long) nNewHeight) - (long) nOldHeight );
2172             mpRowHeights->setValue(nRow, nRow, nNewHeight);
2173 			DecRecalcLevel();
2174 
2175             InvalidatePageBreaks();
2176 		}
2177 	}
2178 	else
2179 	{
2180 		DBG_ERROR("Falsche Zeilennummer oder keine Hoehen");
2181 	}
2182 }
2183 
2184 namespace {
2185 
2186 /**
2187  * Check if the new pixel size is different from the old size between
2188  * specified ranges.
2189  */
2190 bool lcl_pixelSizeChanged(
2191     ScFlatUInt16RowSegments& rRowHeights, SCROW nStartRow, SCROW nEndRow,
2192     sal_uInt16 nNewHeight, double nPPTY)
2193 {
2194     long nNewPix = static_cast<long>(nNewHeight * nPPTY);
2195 
2196     ScFlatUInt16RowSegments::ForwardIterator aFwdIter(rRowHeights);
2197     for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
2198     {
2199         sal_uInt16 nHeight;
2200         if (!aFwdIter.getValue(nRow, nHeight))
2201             break;
2202 
2203         if (nHeight != nNewHeight)
2204         {
2205             bool bChanged = (nNewPix != static_cast<long>(nHeight * nPPTY));
2206             if (bChanged)
2207                 return true;
2208         }
2209 
2210         // Skip ahead to the last position of the current range.
2211         nRow = aFwdIter.getLastPos();
2212     }
2213     return false;
2214 }
2215 
2216 }
2217 
2218 sal_Bool ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight,
2219                                     double /* nPPTX */, double nPPTY )
2220 {
2221 	sal_Bool bChanged = sal_False;
2222     if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights)
2223 	{
2224 		IncRecalcLevel();
2225         InitializeNoteCaptions();
2226 		if (!nNewHeight)
2227 		{
2228 			DBG_ERROR("Zeilenhoehe 0 in SetRowHeight");
2229 			nNewHeight = ScGlobal::nStdRowHeight;
2230 		}
2231 
2232         sal_Bool bSingle = sal_False;   // sal_True = process every row for its own
2233 		ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2234 		if (pDrawLayer)
2235 			if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow ))
2236 				bSingle = sal_True;
2237 
2238 		if (bSingle)
2239 		{
2240             ScFlatUInt16RowSegments::RangeData aData;
2241             mpRowHeights->getRangeData(nStartRow, aData);
2242             if (nNewHeight == aData.mnValue && nEndRow <= aData.mnRow2)
2243                 bSingle = sal_False;    // no difference in this range
2244 		}
2245 		if (bSingle)
2246 		{
2247 			if (nEndRow-nStartRow < 20)
2248             {
2249                 if (!bChanged)
2250                     bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2251 
2252                 /*  #i94028# #i94991# If drawing objects are involved, each row
2253                     has to be changed for its own, because each call to
2254                     ScDrawLayer::HeightChanged expects correct row heights
2255                     above passed row in the document. Cannot use array iterator
2256                     because array changes in every cycle. */
2257                 if( pDrawLayer )
2258                 {
2259                     for( SCROW nRow = nStartRow; nRow <= nEndRow ; ++nRow )
2260                     {
2261                         pDrawLayer->HeightChanged( nTab, nRow,
2262                              static_cast<long>(nNewHeight) - static_cast<long>(mpRowHeights->getValue(nRow)));
2263                         mpRowHeights->setValue(nRow, nRow, nNewHeight);
2264                     }
2265                 }
2266                 else
2267                     mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2268             }
2269 			else
2270 			{
2271 				SCROW nMid = (nStartRow+nEndRow) / 2;
2272 				if (SetRowHeightRange( nStartRow, nMid, nNewHeight, 1.0, 1.0 ))
2273 					bChanged = sal_True;
2274 				if (SetRowHeightRange( nMid+1, nEndRow, nNewHeight, 1.0, 1.0 ))
2275 					bChanged = sal_True;
2276 			}
2277 		}
2278 		else
2279 		{
2280 			if (pDrawLayer)
2281 			{
2282                 // #i115025# When comparing to nNewHeight for the whole range, the height
2283                 // including hidden rows has to be used (same behavior as 3.2).
2284                 unsigned long nOldHeights = mpRowHeights->getSumValue(nStartRow, nEndRow);
2285                 // FIXME: should we test for overflows?
2286 				long nHeightDif = (long) (unsigned long) nNewHeight *
2287                     (nEndRow - nStartRow + 1) - nOldHeights;
2288 				pDrawLayer->HeightChanged( nTab, nEndRow, nHeightDif );
2289 			}
2290 
2291             if (!bChanged)
2292                 bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2293 
2294             mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2295 		}
2296 		DecRecalcLevel();
2297 
2298         if (bChanged)
2299             InvalidatePageBreaks();
2300 	}
2301 	else
2302 	{
2303 		DBG_ERROR("Falsche Zeilennummer oder keine Hoehen");
2304 	}
2305 
2306 	return bChanged;
2307 }
2308 
2309 void ScTable::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight )
2310 {
2311     if (!ValidRow(nStartRow) || !ValidRow(nEndRow) || !mpRowHeights)
2312         return;
2313 
2314     if (!nNewHeight)
2315         nNewHeight = ScGlobal::nStdRowHeight;
2316 
2317     mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2318 }
2319 
2320 void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, sal_Bool bManual )
2321 {
2322 	if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags)
2323 	{
2324 		if (bManual)
2325             pRowFlags->OrValue( nStartRow, nEndRow, CR_MANUALSIZE);
2326 		else
2327             pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
2328 	}
2329 	else
2330 	{
2331 		DBG_ERROR("Falsche Zeilennummer oder keine Zeilenflags");
2332 	}
2333 }
2334 
2335 
2336 sal_uInt16 ScTable::GetColWidth( SCCOL nCol ) const
2337 {
2338 	DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
2339 
2340 	if (VALIDCOL(nCol) && pColFlags && pColWidth)
2341 	{
2342         if (ColHidden(nCol))
2343 			return 0;
2344 		else
2345 			return pColWidth[nCol];
2346 	}
2347 	else
2348 		return (sal_uInt16) STD_COL_WIDTH;
2349 }
2350 
2351 
2352 sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const		// immer die eingestellte
2353 {
2354 	DBG_ASSERT(VALIDCOL(nCol),"Falsche Spaltennummer");
2355 
2356 	if (VALIDCOL(nCol) && pColWidth)
2357 		return pColWidth[nCol];
2358 	else
2359 		return (sal_uInt16) STD_COL_WIDTH;
2360 }
2361 
2362 
2363 sal_uInt16 ScTable::GetCommonWidth( SCCOL nEndCol )
2364 {
2365 	//	get the width that is used in the largest continuous column range (up to nEndCol)
2366 
2367 	if ( !ValidCol(nEndCol) )
2368 	{
2369 		DBG_ERROR("wrong column");
2370 		nEndCol = MAXCOL;
2371 	}
2372 
2373 	sal_uInt16 nMaxWidth = 0;
2374 	sal_uInt16 nMaxCount = 0;
2375 	SCCOL nRangeStart = 0;
2376 	while ( nRangeStart <= nEndCol )
2377 	{
2378 		//	skip hidden columns
2379 		while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) )
2380 			++nRangeStart;
2381 		if ( nRangeStart <= nEndCol )
2382 		{
2383 			sal_uInt16 nThisCount = 0;
2384 			sal_uInt16 nThisWidth = pColWidth[nRangeStart];
2385 			SCCOL nRangeEnd = nRangeStart;
2386 			while ( nRangeEnd <= nEndCol && pColWidth[nRangeEnd] == nThisWidth )
2387 			{
2388 				++nThisCount;
2389 				++nRangeEnd;
2390 
2391 				//	skip hidden columns
2392 				while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) )
2393 					++nRangeEnd;
2394 			}
2395 
2396 			if ( nThisCount > nMaxCount )
2397 			{
2398 				nMaxCount = nThisCount;
2399 				nMaxWidth = nThisWidth;
2400 			}
2401 
2402 			nRangeStart = nRangeEnd;		// next range
2403 		}
2404 	}
2405 
2406 	return nMaxWidth;
2407 }
2408 
2409 
2410 sal_uInt16 ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
2411 {
2412     DBG_ASSERT(VALIDROW(nRow),"Invalid row number");
2413 
2414     if (VALIDROW(nRow) && mpRowHeights)
2415     {
2416         if (bHiddenAsZero && RowHidden( nRow, pStartRow, pEndRow))
2417             return 0;
2418         else
2419         {
2420             ScFlatUInt16RowSegments::RangeData aData;
2421             if (!mpRowHeights->getRangeData(nRow, aData))
2422             {
2423                 if (pStartRow)
2424                     *pStartRow = nRow;
2425                 if (pEndRow)
2426                     *pEndRow = nRow;
2427                 // TODO: What should we return in case the search fails?
2428                 return 0;
2429             }
2430 
2431             // If bHiddenAsZero, pStartRow and pEndRow were initialized to
2432             // boundaries of a non-hidden segment. Assume that the previous and
2433             // next segment are hidden then and limit the current height
2434             // segment.
2435             if (pStartRow)
2436                 *pStartRow = (bHiddenAsZero ? std::max( *pStartRow, aData.mnRow1) : aData.mnRow1);
2437             if (pEndRow)
2438                 *pEndRow = (bHiddenAsZero ? std::min( *pEndRow, aData.mnRow2) : aData.mnRow2);
2439             return aData.mnValue;
2440         }
2441     }
2442     else
2443     {
2444         if (pStartRow)
2445             *pStartRow = nRow;
2446         if (pEndRow)
2447             *pEndRow = nRow;
2448         return (sal_uInt16) ScGlobal::nStdRowHeight;
2449     }
2450 }
2451 
2452 
2453 sal_uLong ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow ) const
2454 {
2455 	DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer");
2456 
2457 	if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights)
2458 	{
2459         sal_uLong nHeight = 0;
2460         SCROW nRow = nStartRow;
2461         while (nRow <= nEndRow)
2462         {
2463             SCROW nLastRow = -1;
2464             if (!RowHidden(nRow, nLastRow))
2465             {
2466                 if (nLastRow > nEndRow)
2467                     nLastRow = nEndRow;
2468                 nHeight += mpRowHeights->getSumValue(nRow, nLastRow);
2469             }
2470             nRow = nLastRow + 1;
2471         }
2472         return nHeight;
2473 	}
2474 	else
2475 		return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight);
2476 }
2477 
2478 
2479 sal_uLong ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const
2480 {
2481 	DBG_ASSERT(VALIDROW(nStartRow) && VALIDROW(nEndRow),"Falsche Zeilennummer");
2482 
2483 	if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && mpRowHeights)
2484 	{
2485         sal_uLong nHeight = 0;
2486         SCROW nRow = nStartRow;
2487         while (nRow <= nEndRow)
2488         {
2489             SCROW nLastRow = -1;
2490             if (!RowHidden(nRow, nLastRow))
2491             {
2492                 if (nLastRow > nEndRow)
2493                     nLastRow = nEndRow;
2494 
2495                 // #i117315# can't use getSumValue, because individual values must be rounded
2496                 while (nRow <= nLastRow)
2497                 {
2498                     ScFlatUInt16RowSegments::RangeData aData;
2499                     if (!mpRowHeights->getRangeData(nRow, aData))
2500                         return nHeight;   // shouldn't happen
2501 
2502                     SCROW nSegmentEnd = std::min( nLastRow, aData.mnRow2 );
2503 
2504                     // round-down a single height value, multiply resulting (pixel) values
2505                     sal_uLong nOneHeight = static_cast<sal_uLong>( aData.mnValue * fScale );
2506                     nHeight += nOneHeight * ( nSegmentEnd + 1 - nRow );
2507 
2508                     nRow = nSegmentEnd + 1;
2509                 }
2510             }
2511             nRow = nLastRow + 1;
2512         }
2513         return nHeight;
2514 	}
2515 	else
2516 		return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight * fScale);
2517 }
2518 
2519 
2520 sal_uInt16 ScTable::GetOriginalHeight( SCROW nRow ) const		// non-0 even if hidden
2521 {
2522 	DBG_ASSERT(VALIDROW(nRow),"wrong row number");
2523 
2524     if (VALIDROW(nRow) && mpRowHeights)
2525         return mpRowHeights->getValue(nRow);
2526 	else
2527 		return (sal_uInt16) ScGlobal::nStdRowHeight;
2528 }
2529 
2530 
2531 //	Spalten-/Zeilen-Flags
2532 
2533 
2534 SCROW ScTable::GetHiddenRowCount( SCROW nRow )
2535 {
2536     if (!ValidRow(nRow))
2537         return 0;
2538 
2539     SCROW nLastRow = -1;
2540     if (!RowHidden(nRow, nLastRow) || !ValidRow(nLastRow))
2541         return 0;
2542 
2543     return nLastRow - nRow + 1;
2544 }
2545 
2546 
2547 //!		ShowRows / DBShowRows zusammenfassen
2548 
2549 void ScTable::ShowCol(SCCOL nCol, bool bShow)
2550 {
2551 	if (VALIDCOL(nCol))
2552 	{
2553         bool bWasVis = !ColHidden(nCol);
2554 		if (bWasVis != bShow)
2555 		{
2556 			IncRecalcLevel();
2557             InitializeNoteCaptions();
2558 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2559 			if (pDrawLayer)
2560 			{
2561 				if (bShow)
2562 					pDrawLayer->WidthChanged( nTab, nCol, (long) pColWidth[nCol] );
2563 				else
2564 					pDrawLayer->WidthChanged( nTab, nCol, -(long) pColWidth[nCol] );
2565 			}
2566 
2567             SetColHidden(nCol, nCol, !bShow);
2568 	    DecRecalcLevel();
2569 
2570 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2571 			if ( pCharts )
2572 				pCharts->SetRangeDirty(ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ));
2573 		}
2574 	}
2575 	else
2576 	{
2577 		DBG_ERROR("Falsche Spaltennummer oder keine Flags");
2578 	}
2579 }
2580 
2581 
2582 void ScTable::ShowRow(SCROW nRow, bool bShow)
2583 {
2584 	if (VALIDROW(nRow) && pRowFlags)
2585 	{
2586         bool bWasVis = !RowHidden(nRow);
2587 		if (bWasVis != bShow)
2588 		{
2589 			IncRecalcLevel();
2590             InitializeNoteCaptions();
2591 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2592 			if (pDrawLayer)
2593 			{
2594 				if (bShow)
2595                     pDrawLayer->HeightChanged(
2596                         nTab, nRow, static_cast<long>(mpRowHeights->getValue(nRow)));
2597 				else
2598                     pDrawLayer->HeightChanged(
2599                         nTab, nRow, -static_cast<long>(mpRowHeights->getValue(nRow)));
2600 			}
2601 
2602             SetRowHidden(nRow, nRow, !bShow);
2603 			if (bShow)
2604                 SetRowFiltered(nRow, nRow, false);
2605 		DecRecalcLevel();
2606 
2607 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2608 			if ( pCharts )
2609 				pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
2610 
2611             InvalidatePageBreaks();
2612 		}
2613 	}
2614 	else
2615 	{
2616 		DBG_ERROR("Falsche Zeilennummer oder keine Flags");
2617 	}
2618 }
2619 
2620 
2621 void ScTable::DBShowRow(SCROW nRow, bool bShow)
2622 {
2623 	if (VALIDROW(nRow) && pRowFlags)
2624 	{
2625         bool bWasVis = !RowHidden(nRow);
2626 		IncRecalcLevel();
2627         InitializeNoteCaptions();
2628 		if (bWasVis != bShow)
2629 		{
2630 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2631 			if (pDrawLayer)
2632 			{
2633 				if (bShow)
2634                     pDrawLayer->HeightChanged(
2635                         nTab, nRow, static_cast<long>(mpRowHeights->getValue(nRow)));
2636 				else
2637                     pDrawLayer->HeightChanged(
2638                         nTab, nRow, -static_cast<long>(mpRowHeights->getValue(nRow)));
2639 			}
2640 		}
2641 
2642 		//	Filter-Flag immer setzen, auch wenn Hidden unveraendert
2643         SetRowHidden(nRow, nRow, !bShow);
2644         SetRowFiltered(nRow, nRow, !bShow);
2645 	DecRecalcLevel();
2646 
2647 		if (bWasVis != bShow)
2648 		{
2649 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2650 			if ( pCharts )
2651 				pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
2652 
2653 			if (pOutlineTable)
2654 				UpdateOutlineRow( nRow, nRow, bShow );
2655 
2656             InvalidatePageBreaks();
2657 		}
2658 	}
2659 	else
2660 	{
2661 		DBG_ERROR("Falsche Zeilennummer oder keine Flags");
2662 	}
2663 }
2664 
2665 
2666 void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow, bool bSetFlags)
2667 {
2668     // #i116164# IncRecalcLevel/DecRecalcLevel is in ScTable::Query
2669 	SCROW nStartRow = nRow1;
2670     InitializeNoteCaptions();
2671 	while (nStartRow <= nRow2)
2672 	{
2673         SCROW nEndRow = -1;
2674         bool bWasVis = !RowHidden(nStartRow, nEndRow);
2675         if (nEndRow > nRow2)
2676             nEndRow = nRow2;
2677 
2678 		sal_Bool bChanged = ( bWasVis != bShow );
2679 		if ( bChanged && bSetFlags )
2680 		{
2681 			ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2682 			if (pDrawLayer)
2683 			{
2684                 long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow));
2685 				if (bShow)
2686 					pDrawLayer->HeightChanged( nTab, nStartRow, nHeight );
2687 				else
2688 					pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight );
2689 			}
2690 		}
2691 
2692         // #i116164# Directly modify the flags only if there are drawing objects within the area.
2693         // Otherwise, all modifications are made together in ScTable::Query, so the tree isn't constantly rebuilt.
2694         if ( bSetFlags )
2695         {
2696             SetRowHidden(nStartRow, nEndRow, !bShow);
2697             SetRowFiltered(nStartRow, nEndRow, !bShow);
2698         }
2699 
2700 		if ( bChanged )
2701 		{
2702 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2703 			if ( pCharts )
2704 				pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
2705 		}
2706 
2707 		nStartRow = nEndRow + 1;
2708 	}
2709 
2710 	//	#i12341# For Show/Hide rows, the outlines are updated separately from the outside.
2711 	//	For filtering, the changes aren't visible to the caller, so UpdateOutlineRow has
2712 	//	to be done here.
2713 	if (pOutlineTable)
2714 		UpdateOutlineRow( nRow1, nRow2, bShow );
2715 }
2716 
2717 
2718 void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
2719 {
2720 	SCROW nStartRow = nRow1;
2721 	IncRecalcLevel();
2722     InitializeNoteCaptions();
2723 
2724     // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough
2725     ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2726     bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2, false );
2727     long nOldHeight = 0;
2728     if ( pDrawLayer && !bHasObjects )
2729         nOldHeight = static_cast<long>(GetRowHeight(nRow1, nRow2));
2730 
2731 	while (nStartRow <= nRow2)
2732 	{
2733         SCROW nEndRow = -1;
2734         bool bWasVis = !RowHidden(nStartRow, nEndRow);
2735         if (nEndRow > nRow2)
2736             nEndRow = nRow2;
2737 
2738 		sal_Bool bChanged = ( bWasVis != bShow );
2739         if ( bChanged && bHasObjects )
2740 		{
2741 			if (pDrawLayer)
2742 			{
2743                 long nHeight = static_cast<long>(mpRowHeights->getSumValue(nStartRow, nEndRow));
2744 				if (bShow)
2745 					pDrawLayer->HeightChanged( nTab, nStartRow, nHeight );
2746 				else
2747 					pDrawLayer->HeightChanged( nTab, nStartRow, -nHeight );
2748 			}
2749 		}
2750 
2751         // #i116164# Directly modify the flags only if there are drawing objects within the area.
2752         // Otherwise, all rows are modified together after the loop, so the tree isn't constantly rebuilt.
2753         if ( bHasObjects )
2754         {
2755             SetRowHidden(nStartRow, nEndRow, !bShow);
2756             if (bShow)
2757                 SetRowFiltered(nStartRow, nEndRow, false);
2758         }
2759 
2760 		if ( bChanged )
2761 		{
2762 			ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
2763 			if ( pCharts )
2764 				pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
2765 
2766             InvalidatePageBreaks();
2767 		}
2768 
2769 		nStartRow = nEndRow + 1;
2770 	}
2771 
2772     if ( !bHasObjects )
2773     {
2774         // #i116164# set the flags for the whole range at once
2775         SetRowHidden(nRow1, nRow2, !bShow);
2776         if (bShow)
2777             SetRowFiltered(nRow1, nRow2, false);
2778 
2779         if ( pDrawLayer )
2780         {
2781             // if there are no objects in the range, a single HeightChanged call is enough
2782             long nNewHeight = 0;
2783             if ( bShow )
2784                 nNewHeight = static_cast<long>(GetRowHeight(nRow1, nRow2));
2785             if ( nNewHeight != nOldHeight )
2786                 pDrawLayer->HeightChanged( nTab, nRow1, nNewHeight - nOldHeight );
2787         }
2788     }
2789 
2790 	DecRecalcLevel();
2791 }
2792 
2793 sal_Bool ScTable::IsDataFiltered() const
2794 {
2795 	sal_Bool bAnyQuery = sal_False;
2796 	ScDBData* pDBData = pDocument->GetFilterDBAtTable(nTab);
2797 	if ( pDBData )
2798 	{
2799 		ScQueryParam aParam;
2800 		pDBData->GetQueryParam( aParam );
2801 		if ( aParam.GetEntry(0).bDoQuery )
2802 			bAnyQuery = sal_True;
2803 	}
2804 	return bAnyQuery;
2805 }
2806 
2807 void ScTable::SetColFlags( SCCOL nCol, sal_uInt8 nNewFlags )
2808 {
2809 	if (VALIDCOL(nCol) && pColFlags)
2810 		pColFlags[nCol] = nNewFlags;
2811 	else
2812 	{
2813 		DBG_ERROR("Falsche Spaltennummer oder keine Flags");
2814 	}
2815 }
2816 
2817 
2818 void ScTable::SetRowFlags( SCROW nRow, sal_uInt8 nNewFlags )
2819 {
2820 	if (VALIDROW(nRow) && pRowFlags)
2821 		pRowFlags->SetValue( nRow, nNewFlags);
2822 	else
2823 	{
2824 		DBG_ERROR("Falsche Zeilennummer oder keine Flags");
2825 	}
2826 }
2827 
2828 
2829 void ScTable::SetRowFlags( SCROW nStartRow, SCROW nEndRow, sal_uInt8 nNewFlags )
2830 {
2831 	if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowFlags)
2832 		pRowFlags->SetValue( nStartRow, nEndRow, nNewFlags);
2833 	else
2834 	{
2835 		DBG_ERROR("Falsche Zeilennummer(n) oder keine Flags");
2836 	}
2837 }
2838 
2839 
2840 sal_uInt8 ScTable::GetColFlags( SCCOL nCol ) const
2841 {
2842 	if (VALIDCOL(nCol) && pColFlags)
2843 		return pColFlags[nCol];
2844 	else
2845 		return 0;
2846 }
2847 
2848 
2849 sal_uInt8 ScTable::GetRowFlags( SCROW nRow ) const
2850 {
2851 	if (VALIDROW(nRow) && pRowFlags)
2852 		return pRowFlags->GetValue(nRow);
2853 	else
2854 		return 0;
2855 }
2856 
2857 
2858 SCROW ScTable::GetLastFlaggedRow() const
2859 {
2860     SCROW nLastFound = 0;
2861     if (pRowFlags)
2862     {
2863         SCROW nRow = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<sal_uInt8>(CR_ALL) );
2864         if (ValidRow(nRow))
2865             nLastFound = nRow;
2866     }
2867 
2868     if (!maRowManualBreaks.empty())
2869         nLastFound = ::std::max(nLastFound, *maRowManualBreaks.rbegin());
2870 
2871     if (mpHiddenRows)
2872     {
2873         SCROW nRow = mpHiddenRows->findLastNotOf(false);
2874         if (ValidRow(nRow))
2875             nLastFound = ::std::max(nLastFound, nRow);
2876     }
2877 
2878     if (mpFilteredRows)
2879     {
2880         SCROW nRow = mpFilteredRows->findLastNotOf(false);
2881         if (ValidRow(nRow))
2882             nLastFound = ::std::max(nLastFound, nRow);
2883     }
2884 
2885     return nLastFound;
2886 }
2887 
2888 
2889 SCCOL ScTable::GetLastChangedCol() const
2890 {
2891 	if ( !pColFlags )
2892 		return 0;
2893 
2894 	SCCOL nLastFound = 0;
2895 	for (SCCOL nCol = 1; nCol <= MAXCOL; nCol++)
2896         if ((pColFlags[nCol] & CR_ALL) || (pColWidth[nCol] != STD_COL_WIDTH))
2897 			nLastFound = nCol;
2898 
2899 	return nLastFound;
2900 }
2901 
2902 
2903 SCROW ScTable::GetLastChangedRow() const
2904 {
2905 	if ( !pRowFlags )
2906 		return 0;
2907 
2908     SCROW nLastFlags = GetLastFlaggedRow();
2909 
2910     // Find the last row position where the height is NOT the standard row
2911     // height.
2912     // KOHEI: Test this to make sure it does what it's supposed to.
2913     SCROW nLastHeight = mpRowHeights->findLastNotOf(ScGlobal::nStdRowHeight);
2914     if (!ValidRow(nLastHeight))
2915         nLastHeight = 0;
2916 
2917 	return std::max( nLastFlags, nLastHeight);
2918 }
2919 
2920 
2921 sal_Bool ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, sal_Bool bShow )
2922 {
2923 	if (pOutlineTable && pColFlags)
2924     {
2925         ScBitMaskCompressedArray< SCCOLROW, sal_uInt8> aArray( MAXCOL, pColFlags, MAXCOLCOUNT);
2926 		return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, *this, true );
2927     }
2928 	else
2929 		return sal_False;
2930 }
2931 
2932 
2933 sal_Bool ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, sal_Bool bShow )
2934 {
2935 	if (pOutlineTable && pRowFlags)
2936 		return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, *this, false );
2937 	else
2938 		return sal_False;
2939 }
2940 
2941 
2942 void ScTable::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
2943 {
2944     // Column-wise expansion
2945 
2946     while (rX1 > 0 && ColHidden(rX1-1))
2947         --rX1;
2948 
2949     while (rX2 < MAXCOL && ColHidden(rX2+1))
2950         ++rX2;
2951 
2952     // Row-wise expansion
2953 
2954     if (rY1 > 0)
2955 	{
2956         ScFlatBoolRowSegments::RangeData aData;
2957         if (mpHiddenRows->getRangeData(rY1-1, aData) && aData.mbValue)
2958         {
2959             SCROW nStartRow = aData.mnRow1;
2960             if (ValidRow(nStartRow))
2961                 rY1 = nStartRow;
2962         }
2963     }
2964     if (rY2 < MAXROW)
2965     {
2966         SCROW nEndRow = -1;
2967         if (RowHidden(rY2+1, nEndRow) && ValidRow(nEndRow))
2968             rY2 = nEndRow;
2969 	}
2970 }
2971 
2972 
2973 void ScTable::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
2974 {
2975     while ( rX2>rX1 && ColHidden(rX2) )
2976         --rX2;
2977     while ( rX2>rX1 && ColHidden(rX1) )
2978         ++rX1;
2979 
2980     if (rY1 < rY2)
2981 	{
2982         ScFlatBoolRowSegments::RangeData aData;
2983         if (mpHiddenRows->getRangeData(rY2, aData) && aData.mbValue)
2984         {
2985             SCROW nStartRow = aData.mnRow1;
2986             if (ValidRow(nStartRow) && nStartRow >= rY1)
2987                 rY2 = nStartRow;
2988         }
2989     }
2990 
2991     if (rY1 < rY2)
2992     {
2993         SCROW nEndRow = -1;
2994         if (RowHidden(rY1, nEndRow) && ValidRow(nEndRow) && nEndRow <= rY2)
2995             rY1 = nEndRow;
2996 	}
2997 }
2998 
2999 
3000 //	Auto-Outline
3001 
3002 template< typename T >
3003 short DiffSign( T a, T b )
3004 {
3005 	return (a<b) ? -1 :
3006 			(a>b) ? 1 : 0;
3007 }
3008 
3009 
3010 void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
3011 {
3012 	sal_Bool bSizeChanged = sal_False;
3013 	sal_Bool bMissed	  = sal_False;
3014 
3015 	SCCOL nCol;
3016 	SCROW nRow;
3017 	SCROW i;
3018 	sal_Bool bFound;
3019 	ScOutlineArray* pArray;
3020 	ScBaseCell* pCell;
3021 	ScRange aRef;
3022 /*	ScPatternAttr aBoldPattern( pDocument->GetPool() );				//!	spezielle Format-Vorlage
3023 	aBoldPattern.GetItemSet().Put( SvxWeightItem( WEIGHT_BOLD ) );
3024 */
3025 
3026 	StartOutlineTable();
3027 
3028 							// Zeilen
3029 
3030 	SCROW	nCount = nEndRow-nStartRow+1;
3031 	sal_Bool*	pUsed = new sal_Bool[nCount];
3032 	for (i=0; i<nCount; i++)
3033 		pUsed[i] = sal_False;
3034 	for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3035 		if (!aCol[nCol].IsEmptyData())
3036 			aCol[nCol].FindUsed( nStartRow, nEndRow, pUsed );
3037 
3038 	pArray = pOutlineTable->GetRowArray();
3039 	for (nRow=nStartRow; nRow<=nEndRow; nRow++)
3040 		if (pUsed[nRow-nStartRow])
3041 		{
3042 			bFound = sal_False;
3043 			for (nCol=nStartCol; nCol<=nEndCol && !bFound; nCol++)
3044 				if (!aCol[nCol].IsEmptyData())
3045 				{
3046 					pCell = aCol[nCol].GetCell( nRow );
3047 					if (pCell)
3048 						if ( pCell->GetCellType() == CELLTYPE_FORMULA )
3049 							if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
3050 								if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
3051 									 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
3052 									 DiffSign( aRef.aStart.Row(), nRow ) ==
3053 										DiffSign( aRef.aEnd.Row(), nRow ) )
3054 								{
3055 									if (pArray->Insert( aRef.aStart.Row(), aRef.aEnd.Row(), bSizeChanged ))
3056 									{
3057 //										ApplyPatternArea( nStartCol, nRow, nEndCol, nRow, aBoldPattern );
3058 										bFound = sal_True;
3059 									}
3060 									else
3061 										bMissed = sal_True;
3062 								}
3063 				}
3064 		}
3065 
3066 	delete[] pUsed;
3067 
3068 							// Spalten
3069 
3070 	pArray = pOutlineTable->GetColArray();
3071 	for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3072 	{
3073 		if (!aCol[nCol].IsEmptyData())
3074 		{
3075 			bFound = sal_False;
3076 			ScColumnIterator aIter( &aCol[nCol], nStartRow, nEndRow );
3077 			while ( aIter.Next( nRow, pCell ) && !bFound )
3078 			{
3079 				if ( pCell->GetCellType() == CELLTYPE_FORMULA )
3080 					if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef ))
3081 						if ( aRef.aStart.Row() == nRow && aRef.aEnd.Row() == nRow &&
3082 							 aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
3083 							 DiffSign( aRef.aStart.Col(), nCol ) ==
3084 								DiffSign( aRef.aEnd.Col(), nCol ) )
3085 						{
3086 							if (pArray->Insert( aRef.aStart.Col(), aRef.aEnd.Col(), bSizeChanged ))
3087 							{
3088 //								ApplyPatternArea( nCol, nStartRow, nCol, nEndRow, aBoldPattern );
3089 								bFound = sal_True;
3090 							}
3091 							else
3092 								bMissed = sal_True;
3093 						}
3094 			}
3095 		}
3096 	}
3097 }
3098 
3099 									//	CopyData - fuer Query in anderen Bereich
3100 
3101 void ScTable::CopyData( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
3102 							SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab )
3103 {
3104 	//!		wenn fuer mehrere Zeilen benutzt, nach Spalten optimieren!
3105 
3106 	ScAddress aSrc( nStartCol, nStartRow, nTab );
3107 	ScAddress aDest( nDestCol, nDestRow, nDestTab );
3108 	ScRange aRange( aSrc, aDest );
3109 	sal_Bool bThisTab = ( nDestTab == nTab );
3110 	SCROW nDestY = nDestRow;
3111 	for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
3112 	{
3113 		aSrc.SetRow( nRow );
3114 		aDest.SetRow( nDestY );
3115 		SCCOL nDestX = nDestCol;
3116 		for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
3117 		{
3118 			aSrc.SetCol( nCol );
3119 			aDest.SetCol( nDestX );
3120 			ScBaseCell* pCell = GetCell( nCol, nRow );
3121 			if (pCell)
3122 			{
3123                 pCell = pCell->CloneWithoutNote( *pDocument );
3124 				if (pCell->GetCellType() == CELLTYPE_FORMULA)
3125 				{
3126 					((ScFormulaCell*)pCell)->UpdateReference( URM_COPY, aRange,
3127 									((SCsCOL) nDestCol) - ((SCsCOL) nStartCol),
3128 									((SCsROW) nDestRow) - ((SCsROW) nStartRow),
3129 									((SCsTAB) nDestTab) - ((SCsTAB) nTab) );
3130 					((ScFormulaCell*)pCell)->aPos = aDest;
3131 				}
3132 			}
3133 			if (bThisTab)
3134 			{
3135 				PutCell( nDestX, nDestY, pCell );
3136 				SetPattern( nDestX, nDestY, *GetPattern( nCol, nRow ), sal_True );
3137 			}
3138 			else
3139 			{
3140 				pDocument->PutCell( aDest, pCell );
3141 				pDocument->SetPattern( aDest, *GetPattern( nCol, nRow ), sal_True );
3142 			}
3143 
3144 			++nDestX;
3145 		}
3146 		++nDestY;
3147 	}
3148 }
3149 
3150 
3151 sal_Bool ScTable::RefVisible(ScFormulaCell* pCell)
3152 {
3153 	ScRange aRef;
3154 
3155 	if (pCell->HasOneReference(aRef))
3156 	{
3157 		if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab())
3158 		{
3159             SCROW nEndRow;
3160             if (!RowFiltered(aRef.aStart.Row(), NULL, &nEndRow))
3161                 // row not filtered.
3162                 nEndRow = ::std::numeric_limits<SCROW>::max();
3163 
3164             if (!ValidRow(nEndRow) || nEndRow < aRef.aEnd.Row())
3165                 return sal_True;    // at least partly visible
3166             return sal_False;       // completely invisible
3167 		}
3168 	}
3169 
3170 	return sal_True;						// irgendwie anders
3171 }
3172 
3173 
3174 void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, String& rStr)
3175 {
3176 	GetInputString(nCol, nRow, rStr);
3177 	rStr.EraseTrailingChars();
3178 	rStr.EraseLeadingChars();
3179 	ScGlobal::pCharClass->toUpper(rStr);
3180 }
3181 
3182 
3183 // Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage
3184 
3185 void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos)
3186 {
3187 	ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
3188 	if( pDrawLayer )
3189 	{
3190         double fValX = GetColOffset( MAXCOL + 1 ) * HMM_PER_TWIPS;
3191         double fValY = GetRowOffset( MAXROW + 1 ) * HMM_PER_TWIPS;
3192         const long nMax = ::std::numeric_limits<long>::max();
3193         // #i113884# Avoid int32 overflow with possible negative results than can cause bad effects.
3194         // If the draw page size is smaller than all rows, only the bottom of the sheet is affected.
3195         long x = ( fValX > (double)nMax ) ? nMax : (long) fValX;
3196         long y = ( fValY > (double)nMax ) ? nMax : (long) fValY;
3197 
3198 		if ( IsLayoutRTL() )		// IsNegativePage
3199 			x = -x;
3200 
3201 		pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( x, y ), bUpdateNoteCaptionPos );
3202 	}
3203 
3204     // #i102616# actions that modify the draw page size count as sheet modification
3205     // (exception: InitDrawLayer)
3206     if (bResetStreamValid && IsStreamValid())
3207         SetStreamValid(sal_False);
3208 }
3209 
3210 
3211 sal_uLong ScTable::GetRowOffset( SCROW nRow ) const
3212 {
3213 	sal_uLong n = 0;
3214     if ( mpHiddenRows && mpRowHeights )
3215 	{
3216         if (nRow == 0)
3217             return 0;
3218         else if (nRow == 1)
3219             return GetRowHeight(0);
3220 
3221         n = GetTotalRowHeight(0, nRow-1);
3222 #ifdef DBG_UTIL
3223         if (n == ::std::numeric_limits<unsigned long>::max())
3224             DBG_ERRORFILE("ScTable::GetRowOffset: row heights overflow");
3225 #endif
3226 	}
3227 	else
3228 	{
3229 		DBG_ERROR("GetRowOffset: Daten fehlen");
3230 	}
3231 	return n;
3232 }
3233 
3234 SCROW ScTable::GetRowForHeight(sal_uLong nHeight) const
3235 {
3236     sal_uInt32 nSum = 0;
3237 
3238     ScFlatBoolRowSegments::RangeData aData;
3239     for (SCROW nRow = 0; nRow <= MAXROW; ++nRow)
3240     {
3241         if (!mpHiddenRows->getRangeData(nRow, aData))
3242             break;
3243 
3244         if (aData.mbValue)
3245         {
3246             nRow = aData.mnRow2;
3247             continue;
3248         }
3249 
3250         sal_uInt32 nNew = mpRowHeights->getValue(nRow);
3251         nSum += nNew;
3252         if (nSum > nHeight)
3253         {
3254             return nRow < MAXROW ? nRow + 1 : MAXROW;
3255         }
3256     }
3257     return -1;
3258 }
3259 
3260 
3261 sal_uLong ScTable::GetColOffset( SCCOL nCol ) const
3262 {
3263 	sal_uLong n = 0;
3264 	if ( pColWidth )
3265 	{
3266 		SCCOL i;
3267 		for( i = 0; i < nCol; i++ )
3268             if (!ColHidden(i))
3269 				n += pColWidth[i];
3270 	}
3271 	else
3272 	{
3273 		DBG_ERROR("GetColumnOffset: Daten fehlen");
3274 	}
3275 	return n;
3276 }
3277 
3278