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