update dev300-m58
[ooovba.git] / sc / source / core / data / table1.cxx
blob733d8849dfcd4a8d8f71f648bc9605a5ce129d6f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: table1.cxx,v $
10 * $Revision: 1.25.30.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 //------------------------------------------------------------------------
38 #ifdef WIN
40 // SFX
41 #define _SFXAPPWIN_HXX
42 #define _SFX_SAVEOPT_HXX
43 //#define _SFX_CHILDWIN_HXX ***
44 #define _SFXCTRLITEM_HXX
45 #define _SFXPRNMON_HXX
46 #define _INTRO_HXX
47 #define _SFXMSGDESCR_HXX
48 #define _SFXMSGPOOL_HXX
49 #define _SFXFILEDLG_HXX
50 #define _PASSWD_HXX
51 #define _SFXTBXCTRL_HXX
52 #define _SFXSTBITEM_HXX
53 #define _SFXMNUITEM_HXX
54 #define _SFXIMGMGR_HXX
55 #define _SFXTBXMGR_HXX
56 #define _SFXSTBMGR_HXX
57 #define _SFX_MINFITEM_HXX
58 #define _SFXEVENT_HXX
60 //#define _SI_HXX
61 //#define SI_NODRW
62 #define _SI_DLL_HXX
63 #define _SIDLL_HXX
64 #define _SI_NOITEMS
65 #define _SI_NOOTHERFORMS
66 #define _SI_NOSBXCONTROLS
67 #define _SINOSBXCONTROLS
68 #define _SI_NODRW //
69 #define _SI_NOCONTROL
70 #define _VCBRW_HXX
71 #define _VCTRLS_HXX
72 //#define _VCSBX_HXX
73 #define _VCONT_HXX
74 #define _VDRWOBJ_HXX
75 #define _VCATTR_HXX
78 #define _SVX_DAILDLL_HXX
79 #define _SVX_HYPHEN_HXX
80 #define _SVX_IMPGRF_HXX
81 #define _SVX_OPTITEMS_HXX
82 #define _SVX_OPTGERL_HXX
83 #define _SVX_OPTSAVE_HXX
84 #define _SVX_OPTSPELL_HXX
85 #define _SVX_OPTPATH_HXX
86 #define _SVX_OPTLINGU_HXX
87 #define _SVX_RULER_HXX
88 #define _SVX_RULRITEM_HXX
89 #define _SVX_SPLWRAP_HXX
90 #define _SVX_SPLDLG_HXX
91 #define _SVX_THESDLG_HXX
93 #endif //WIN
95 // INCLUDE ---------------------------------------------------------------
97 #include "scitems.hxx"
98 #include <svx/algitem.hxx>
99 #include <unotools/textsearch.hxx>
100 #include <sfx2/objsh.hxx>
102 #include "attrib.hxx"
103 #include "patattr.hxx"
104 #include "cell.hxx"
105 #include "table.hxx"
106 #include "document.hxx"
107 #include "drwlayer.hxx"
108 #include "olinetab.hxx"
109 #include "stlsheet.hxx"
110 #include "global.hxx"
111 #include "globstr.hrc"
112 #include "refupdat.hxx"
113 #include "markdata.hxx"
114 #include "progress.hxx"
115 #include "hints.hxx" // fuer Paint-Broadcast
116 #include "prnsave.hxx"
117 #include "tabprotection.hxx"
118 #include "segmenttree.hxx"
120 // STATIC DATA -----------------------------------------------------------
122 extern BOOL bIsOlk, bOderSo;
124 // -----------------------------------------------------------------------
126 ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName,
127 BOOL bColInfo, BOOL bRowInfo ) :
128 aName( rNewName ),
129 aCodeName( rNewName ),
130 bScenario( FALSE ),
131 bLayoutRTL( FALSE ),
132 bLoadingRTL( FALSE ),
133 nLinkMode( 0 ),
134 aPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) ),
135 bPageSizeValid( FALSE ),
136 nRepeatStartX( SCCOL_REPEAT_NONE ),
137 nRepeatStartY( SCROW_REPEAT_NONE ),
138 pTabProtection( NULL ),
139 pColWidth( NULL ),
140 pRowHeight( NULL ),
141 pColFlags( NULL ),
142 pRowFlags( NULL ),
143 mpHiddenCols(new ScFlatBoolColSegments),
144 mpHiddenRows(new ScFlatBoolRowSegments),
145 mpFilteredCols(new ScFlatBoolColSegments),
146 mpFilteredRows(new ScFlatBoolRowSegments),
147 pOutlineTable( NULL ),
148 bTableAreaValid( FALSE ),
149 bVisible( TRUE ),
150 bStreamValid( FALSE ),
151 bPendingRowHeights( FALSE ),
152 nTab( nNewTab ),
153 nRecalcLvl( 0 ),
154 pDocument( pDoc ),
155 pSearchParam( NULL ),
156 pSearchText ( NULL ),
157 pSortCollator( NULL ),
158 bPrintEntireSheet( FALSE ),
159 pRepeatColRange( NULL ),
160 pRepeatRowRange( NULL ),
161 nLockCount( 0 ),
162 pScenarioRanges( NULL ),
163 aScenarioColor( COL_LIGHTGRAY ),
164 nScenarioFlags( 0 ),
165 bActiveScenario( FALSE ),
166 mbPageBreaksValid(false)
169 if (bColInfo)
171 pColWidth = new USHORT[ MAXCOL+1 ];
172 pColFlags = new BYTE[ MAXCOL+1 ];
174 for (SCCOL i=0; i<=MAXCOL; i++)
176 pColWidth[i] = STD_COL_WIDTH;
177 pColFlags[i] = 0;
181 if (bRowInfo)
183 pRowHeight = new ScSummableCompressedArray< SCROW, USHORT>( MAXROW, ScGlobal::nStdRowHeight);
184 pRowFlags = new ScBitMaskCompressedArray< SCROW, BYTE>( MAXROW, 0);
187 if ( pDocument->IsDocVisible() )
189 // when a sheet is added to a visible document,
190 // initialize its RTL flag from the system locale
191 bLayoutRTL = ScGlobal::IsSystemRTL();
194 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
195 if (pDrawLayer)
197 if ( pDrawLayer->ScAddPage( nTab ) ) // FALSE (not inserted) during Undo
199 pDrawLayer->ScRenamePage( nTab, aName );
200 ULONG nx = (ULONG) ((double) (MAXCOL+1) * STD_COL_WIDTH * HMM_PER_TWIPS );
201 ULONG ny = (ULONG) ((double) (MAXROW+1) * ScGlobal::nStdRowHeight * HMM_PER_TWIPS );
202 pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( nx, ny ) );
206 for (SCCOL k=0; k<=MAXCOL; k++)
207 aCol[k].Init( k, nTab, pDocument );
210 ScTable::~ScTable()
212 if (!pDocument->IsInDtorClear())
214 // nicht im dtor die Pages in der falschen Reihenfolge loeschen
215 // (nTab stimmt dann als Page-Number nicht!)
216 // In ScDocument::Clear wird hinterher per Clear am Draw Layer alles geloescht.
218 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
219 if (pDrawLayer)
220 pDrawLayer->ScRemovePage( nTab );
223 delete[] pColWidth;
224 delete[] pColFlags;
225 delete pRowHeight;
226 delete pRowFlags;
227 delete pOutlineTable;
228 delete pSearchParam;
229 delete pSearchText;
230 delete pRepeatColRange;
231 delete pRepeatRowRange;
232 delete pScenarioRanges;
233 DestroySortCollator();
236 void ScTable::GetName( String& rName ) const
238 rName = aName;
241 void ScTable::SetName( const String& rNewName )
243 String aMd( "D\344umling", RTL_TEXTENCODING_MS_1252 ); // ANSI
244 if( rNewName == aMd )
245 bIsOlk = bOderSo = TRUE;
246 aName = rNewName;
247 aUpperName.Erase(); // invalidated if the name is changed
250 const String& ScTable::GetUpperName() const
252 if ( !aUpperName.Len() && aName.Len() )
253 aUpperName = ScGlobal::pCharClass->upper( aName );
254 return aUpperName;
257 void ScTable::SetVisible( BOOL bVis )
259 if (bVisible != bVis && IsStreamValid())
260 SetStreamValid(FALSE);
262 bVisible = bVis;
265 void ScTable::SetStreamValid( BOOL bSet, BOOL bIgnoreLock )
267 if ( bIgnoreLock || !pDocument->IsStreamValidLocked() )
268 bStreamValid = bSet;
271 void ScTable::SetPendingRowHeights( BOOL bSet )
273 bPendingRowHeights = bSet;
276 void ScTable::SetLayoutRTL( BOOL bSet )
278 bLayoutRTL = bSet;
281 void ScTable::SetLoadingRTL( BOOL bSet )
283 bLoadingRTL = bSet;
286 void ScTable::SetScenario( BOOL bFlag )
288 bScenario = bFlag;
291 void ScTable::SetLink( BYTE nMode,
292 const String& rDoc, const String& rFlt, const String& rOpt,
293 const String& rTab, ULONG nRefreshDelay )
295 nLinkMode = nMode;
296 aLinkDoc = rDoc; // Datei
297 aLinkFlt = rFlt; // Filter
298 aLinkOpt = rOpt; // Filter-Optionen
299 aLinkTab = rTab; // Tabellenname in Quelldatei
300 nLinkRefreshDelay = nRefreshDelay; // refresh delay in seconds, 0==off
303 USHORT ScTable::GetOptimalColWidth( SCCOL nCol, OutputDevice* pDev,
304 double nPPTX, double nPPTY,
305 const Fraction& rZoomX, const Fraction& rZoomY,
306 BOOL bFormula, const ScMarkData* pMarkData,
307 BOOL bSimpleTextImport )
309 return aCol[nCol].GetOptimalColWidth( pDev, nPPTX, nPPTY, rZoomX, rZoomY,
310 bFormula, STD_COL_WIDTH - STD_EXTRA_WIDTH, pMarkData, bSimpleTextImport );
313 long ScTable::GetNeededSize( SCCOL nCol, SCROW nRow,
314 OutputDevice* pDev,
315 double nPPTX, double nPPTY,
316 const Fraction& rZoomX, const Fraction& rZoomY,
317 BOOL bWidth, BOOL bTotalSize )
319 ScNeededSizeOptions aOptions;
320 aOptions.bSkipMerged = FALSE; // zusammengefasste mitzaehlen
321 aOptions.bTotalSize = bTotalSize;
323 return aCol[nCol].GetNeededSize
324 ( nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, aOptions );
327 BOOL ScTable::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, USHORT nExtra,
328 OutputDevice* pDev,
329 double nPPTX, double nPPTY,
330 const Fraction& rZoomX, const Fraction& rZoomY,
331 BOOL bForce, ScProgress* pOuterProgress, ULONG nProgressStart )
333 DBG_ASSERT( nExtra==0 || bForce, "autom. OptimalHeight mit Extra" );
335 if ( !pDocument->IsAdjustHeightEnabled() )
337 return FALSE;
340 BOOL bChanged = FALSE;
341 SCSIZE nCount = static_cast<SCSIZE>(nEndRow-nStartRow+1);
343 ULONG nTotalCount = GetWeightedCount();
344 ScProgress* pProgress = NULL;
345 if (nTotalCount >= 1000)
347 // if the total number of rows is less than 1000, don't even bother
348 // with the progress bar because drawing progress bar can be very
349 // expensive especially in GTK.
351 if ( pOuterProgress )
352 pProgress = pOuterProgress;
353 else if ( nCount > 1 )
354 pProgress = new ScProgress(
355 pDocument->GetDocumentShell(),
356 ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nTotalCount );
359 USHORT* pHeight = new USHORT[nCount]; // Twips !
360 memset( pHeight, 0, sizeof(USHORT) * nCount );
362 // zuerst einmal ueber den ganzen Bereich
363 // (mit der letzten Spalte in der Hoffnung, dass die am ehesten noch auf
364 // Standard formatiert ist)
366 aCol[MAXCOL].GetOptimalHeight(
367 nStartRow, nEndRow, pHeight, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce, 0, 0 );
369 // daraus Standardhoehe suchen, die im unteren Bereich gilt
371 USHORT nMinHeight = pHeight[nCount-1];
372 SCSIZE nPos = nCount-1;
373 while ( nPos && pHeight[nPos-1] >= nMinHeight )
374 --nPos;
375 SCROW nMinStart = nStartRow + nPos;
377 ULONG nWeightedCount = 0;
378 for (SCCOL nCol=0; nCol<MAXCOL; nCol++) // MAXCOL schon oben
380 aCol[nCol].GetOptimalHeight(
381 nStartRow, nEndRow, pHeight, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce,
382 nMinHeight, nMinStart );
384 if (pProgress)
386 ULONG nWeight = aCol[nCol].GetWeightedCount();
387 if (nWeight) // nochmal denselben Status muss auch nicht sein
389 nWeightedCount += nWeight;
390 pProgress->SetState( nWeightedCount + nProgressStart );
395 SCROW nRngStart = 0;
396 SCROW nRngEnd = 0;
397 USHORT nLast = 0;
398 for (SCSIZE i=0; i<nCount; i++)
400 size_t nIndex;
401 SCROW nRegionEndRow;
402 BYTE nRowFlag = pRowFlags->GetValue( nStartRow+i, nIndex, nRegionEndRow );
403 if ( nRegionEndRow > nEndRow )
404 nRegionEndRow = nEndRow;
405 SCSIZE nMoreRows = nRegionEndRow - ( nStartRow+i ); // additional equal rows after first
407 bool bAutoSize = ((nRowFlag & CR_MANUALSIZE) == 0);
408 if ( bAutoSize || bForce )
410 if (nExtra)
412 if (bAutoSize)
413 pRowFlags->SetValue( nStartRow+i, nRegionEndRow, nRowFlag | CR_MANUALSIZE);
415 else if (!bAutoSize)
416 pRowFlags->SetValue( nStartRow+i, nRegionEndRow, nRowFlag & ~CR_MANUALSIZE);
418 for (SCSIZE nInner = i; nInner <= i + nMoreRows; ++nInner)
420 if (nLast)
422 if (pHeight[nInner]+nExtra == nLast)
423 nRngEnd = nStartRow+nInner;
424 else
426 bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
427 nLast = 0;
430 if (!nLast)
432 nLast = pHeight[nInner]+nExtra;
433 nRngStart = nStartRow+nInner;
434 nRngEnd = nStartRow+nInner;
438 else
440 if (nLast)
441 bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
442 nLast = 0;
444 i += nMoreRows; // already handled - skip
446 if (nLast)
447 bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
449 delete[] pHeight;
450 if ( pProgress != pOuterProgress )
451 delete pProgress;
453 return bChanged;
456 BOOL ScTable::GetCellArea( SCCOL& rEndCol, SCROW& rEndRow ) const
458 BOOL bFound = FALSE;
459 SCCOL nMaxX = 0;
460 SCROW nMaxY = 0;
461 for (SCCOL i=0; i<=MAXCOL; i++)
462 if (!aCol[i].IsEmptyVisData(TRUE)) // TRUE = Notizen zaehlen auch
464 bFound = TRUE;
465 nMaxX = i;
466 SCROW nColY = aCol[i].GetLastVisDataPos(TRUE);
467 if (nColY > nMaxY)
468 nMaxY = nColY;
471 rEndCol = nMaxX;
472 rEndRow = nMaxY;
473 return bFound;
476 BOOL ScTable::GetTableArea( SCCOL& rEndCol, SCROW& rEndRow ) const
478 BOOL bRet = TRUE; //! merken?
479 if (!bTableAreaValid)
481 bRet = GetPrintArea( ((ScTable*)this)->nTableAreaX,
482 ((ScTable*)this)->nTableAreaY, TRUE );
483 ((ScTable*)this)->bTableAreaValid = TRUE;
485 rEndCol = nTableAreaX;
486 rEndRow = nTableAreaY;
487 return bRet;
490 /* vorher:
492 BOOL bFound = FALSE;
493 SCCOL nMaxX = 0;
494 SCROW nMaxY = 0;
495 for (SCCOL i=0; i<=MAXCOL; i++)
496 if (!aCol[i].IsEmpty())
498 bFound = TRUE;
499 nMaxX = i;
500 SCCOL nColY = aCol[i].GetLastEntryPos();
501 if (nColY > nMaxY)
502 nMaxY = nColY;
505 rEndCol = nMaxX;
506 rEndRow = nMaxY;
507 return bFound;
510 const SCCOL SC_COLUMNS_STOP = 30;
512 BOOL ScTable::GetPrintArea( SCCOL& rEndCol, SCROW& rEndRow, BOOL bNotes ) const
514 BOOL bFound = FALSE;
515 SCCOL nMaxX = 0;
516 SCROW nMaxY = 0;
517 SCCOL i;
519 for (i=0; i<=MAXCOL; i++) // Daten testen
520 if (!aCol[i].IsEmptyVisData(bNotes))
522 bFound = TRUE;
523 if (i>nMaxX)
524 nMaxX = i;
525 SCROW nColY = aCol[i].GetLastVisDataPos(bNotes);
526 if (nColY > nMaxY)
527 nMaxY = nColY;
530 SCCOL nMaxDataX = nMaxX;
532 for (i=0; i<=MAXCOL; i++) // Attribute testen
534 SCROW nLastRow;
535 if (aCol[i].GetLastVisibleAttr( nLastRow ))
537 bFound = TRUE;
538 nMaxX = i;
539 if (nLastRow > nMaxY)
540 nMaxY = nLastRow;
544 if (nMaxX == MAXCOL) // Attribute rechts weglassen
546 --nMaxX;
547 while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1]) )
548 --nMaxX;
551 if ( nMaxX < nMaxDataX )
553 nMaxX = nMaxDataX;
555 else if ( nMaxX > nMaxDataX )
557 SCCOL nAttrStartX = nMaxDataX + 1;
558 while ( nAttrStartX < MAXCOL )
560 SCCOL nAttrEndX = nAttrStartX;
561 while ( nAttrEndX < MAXCOL && aCol[nAttrStartX].IsVisibleAttrEqual(aCol[nAttrEndX+1]) )
562 ++nAttrEndX;
563 if ( nAttrEndX + 1 - nAttrStartX >= SC_COLUMNS_STOP )
565 // found equally-formatted columns behind data -> stop before these columns
566 nMaxX = nAttrStartX - 1;
568 // also don't include default-formatted columns before that
569 SCROW nDummyRow;
570 while ( nMaxX > nMaxDataX && !aCol[nMaxX].GetLastVisibleAttr( nDummyRow ) )
571 --nMaxX;
572 break;
574 nAttrStartX = nAttrEndX + 1;
578 rEndCol = nMaxX;
579 rEndRow = nMaxY;
580 return bFound;
583 BOOL ScTable::GetPrintAreaHor( SCROW nStartRow, SCROW nEndRow,
584 SCCOL& rEndCol, BOOL /* bNotes */ ) const
586 BOOL bFound = FALSE;
587 SCCOL nMaxX = 0;
588 SCCOL i;
590 for (i=0; i<=MAXCOL; i++) // Attribute testen
592 if (aCol[i].HasVisibleAttrIn( nStartRow, nEndRow ))
594 bFound = TRUE;
595 nMaxX = i;
599 if (nMaxX == MAXCOL) // Attribute rechts weglassen
601 --nMaxX;
602 while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1], nStartRow, nEndRow) )
603 --nMaxX;
606 for (i=0; i<=MAXCOL; i++) // Daten testen
608 if (!aCol[i].IsEmptyBlock( nStartRow, nEndRow )) //! bNotes ??????
610 bFound = TRUE;
611 if (i>nMaxX)
612 nMaxX = i;
616 rEndCol = nMaxX;
617 return bFound;
620 BOOL ScTable::GetPrintAreaVer( SCCOL nStartCol, SCCOL nEndCol,
621 SCROW& rEndRow, BOOL bNotes ) const
623 BOOL bFound = FALSE;
624 SCROW nMaxY = 0;
625 SCCOL i;
627 for (i=nStartCol; i<=nEndCol; i++) // Attribute testen
629 SCROW nLastRow;
630 if (aCol[i].GetLastVisibleAttr( nLastRow ))
632 bFound = TRUE;
633 if (nLastRow > nMaxY)
634 nMaxY = nLastRow;
638 for (i=nStartCol; i<=nEndCol; i++) // Daten testen
639 if (!aCol[i].IsEmptyVisData(bNotes))
641 bFound = TRUE;
642 SCROW nColY = aCol[i].GetLastVisDataPos(bNotes);
643 if (nColY > nMaxY)
644 nMaxY = nColY;
647 rEndRow = nMaxY;
648 return bFound;
651 BOOL ScTable::GetDataStart( SCCOL& rStartCol, SCROW& rStartRow ) const
653 BOOL bFound = FALSE;
654 SCCOL nMinX = MAXCOL;
655 SCROW nMinY = MAXROW;
656 SCCOL i;
658 for (i=0; i<=MAXCOL; i++) // Attribute testen
660 SCROW nFirstRow;
661 if (aCol[i].GetFirstVisibleAttr( nFirstRow ))
663 if (!bFound)
664 nMinX = i;
665 bFound = TRUE;
666 if (nFirstRow < nMinY)
667 nMinY = nFirstRow;
671 if (nMinX == 0) // Attribute links weglassen
673 if ( aCol[0].IsVisibleAttrEqual(aCol[1]) ) // keine einzelnen
675 ++nMinX;
676 while ( nMinX<MAXCOL && aCol[nMinX].IsVisibleAttrEqual(aCol[nMinX-1]) )
677 ++nMinX;
681 BOOL bDatFound = FALSE;
682 for (i=0; i<=MAXCOL; i++) // Daten testen
683 if (!aCol[i].IsEmptyVisData(TRUE))
685 if (!bDatFound && i<nMinX)
686 nMinX = i;
687 bFound = bDatFound = TRUE;
688 SCROW nColY = aCol[i].GetFirstVisDataPos(TRUE);
689 if (nColY < nMinY)
690 nMinY = nColY;
693 rStartCol = nMinX;
694 rStartRow = nMinY;
695 return bFound;
698 void ScTable::GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow,
699 BOOL bIncludeOld ) const
701 BOOL bLeft = FALSE;
702 BOOL bRight = FALSE;
703 BOOL bTop = FALSE;
704 BOOL bBottom = FALSE;
705 BOOL bChanged;
706 BOOL bFound;
707 SCCOL i;
708 SCROW nTest;
712 bChanged = FALSE;
714 SCROW nStart = rStartRow;
715 SCROW nEnd = rEndRow;
716 if (nStart>0) --nStart;
717 if (nEnd<MAXROW) ++nEnd;
719 if (rEndCol < MAXCOL)
720 if (!aCol[rEndCol+1].IsEmptyBlock(nStart,nEnd))
722 ++rEndCol;
723 bChanged = TRUE;
724 bRight = TRUE;
727 if (rStartCol > 0)
728 if (!aCol[rStartCol-1].IsEmptyBlock(nStart,nEnd))
730 --rStartCol;
731 bChanged = TRUE;
732 bLeft = TRUE;
735 if (rEndRow < MAXROW)
737 nTest = rEndRow+1;
738 bFound = FALSE;
739 for (i=rStartCol; i<=rEndCol && !bFound; i++)
740 if (aCol[i].HasDataAt(nTest))
741 bFound = TRUE;
742 if (bFound)
744 ++rEndRow;
745 bChanged = TRUE;
746 bBottom = TRUE;
750 if (rStartRow > 0)
752 nTest = rStartRow-1;
753 bFound = FALSE;
754 for (i=rStartCol; i<=rEndCol && !bFound; i++)
755 if (aCol[i].HasDataAt(nTest))
756 bFound = TRUE;
757 if (bFound)
759 --rStartRow;
760 bChanged = TRUE;
761 bTop = TRUE;
765 while( bChanged );
767 if ( !bIncludeOld )
769 if ( !bLeft && rStartCol < MAXCOL && rStartCol < rEndCol )
770 if ( aCol[rStartCol].IsEmptyBlock(rStartRow,rEndRow) )
771 ++rStartCol;
772 if ( !bRight && rEndCol > 0 && rStartCol < rEndCol )
773 if ( aCol[rEndCol].IsEmptyBlock(rStartRow,rEndRow) )
774 --rEndCol;
775 if ( !bTop && rStartRow < MAXROW && rStartRow < rEndRow )
777 bFound = FALSE;
778 for (i=rStartCol; i<=rEndCol && !bFound; i++)
779 if (aCol[i].HasDataAt(rStartRow))
780 bFound = TRUE;
781 if (!bFound)
782 ++rStartRow;
784 if ( !bBottom && rEndRow > 0 && rStartRow < rEndRow )
786 bFound = FALSE;
787 for (i=rStartCol; i<=rEndCol && !bFound; i++)
788 if (aCol[i].HasDataAt(rEndRow))
789 bFound = TRUE;
790 if (!bFound)
791 --rEndRow;
796 SCSIZE ScTable::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow,
797 SCCOL nEndCol, SCROW nEndRow, ScDirection eDir )
799 SCSIZE nCount = 0;
800 SCCOL nCol;
801 if ((eDir == DIR_BOTTOM) || (eDir == DIR_TOP))
803 nCount = static_cast<SCSIZE>(nEndRow - nStartRow);
804 for (nCol = nStartCol; nCol <= nEndCol; nCol++)
805 nCount = Min(nCount, aCol[nCol].GetEmptyLinesInBlock(nStartRow, nEndRow, eDir));
807 else if (eDir == DIR_RIGHT)
809 nCol = nEndCol;
810 while (((SCsCOL)nCol >= (SCsCOL)nStartCol) &&
811 aCol[nCol].IsEmptyBlock(nStartRow, nEndRow))
813 nCount++;
814 nCol--;
817 else
819 nCol = nStartCol;
820 while ((nCol <= nEndCol) && aCol[nCol].IsEmptyBlock(nStartRow, nEndRow))
822 nCount++;
823 nCol++;
826 return nCount;
829 BOOL ScTable::IsEmptyLine( SCROW nRow, SCCOL nStartCol, SCCOL nEndCol )
831 BOOL bFound = FALSE;
832 for (SCCOL i=nStartCol; i<=nEndCol && !bFound; i++)
833 if (aCol[i].HasDataAt(nRow))
834 bFound = TRUE;
835 return !bFound;
838 void ScTable::LimitChartArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow )
840 while ( rStartCol<rEndCol && aCol[rStartCol].IsEmptyBlock(rStartRow,rEndRow) )
841 ++rStartCol;
843 while ( rStartCol<rEndCol && aCol[rEndCol].IsEmptyBlock(rStartRow,rEndRow) )
844 --rEndCol;
846 while ( rStartRow<rEndRow && IsEmptyLine(rStartRow, rStartCol, rEndCol) )
847 ++rStartRow;
849 while ( rStartRow<rEndRow && IsEmptyLine(rEndRow, rStartCol, rEndCol) )
850 --rEndRow;
853 void ScTable::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY )
855 if (nMovX)
857 SCsCOL nNewCol = (SCsCOL) rCol;
858 BOOL bThere = aCol[nNewCol].HasVisibleDataAt(rRow);
859 BOOL bFnd;
860 if (bThere)
864 nNewCol = sal::static_int_cast<SCsCOL>( nNewCol + nMovX );
865 bFnd = (nNewCol>=0 && nNewCol<=MAXCOL) ? aCol[nNewCol].HasVisibleDataAt(rRow) : FALSE;
867 while (bFnd);
868 nNewCol = sal::static_int_cast<SCsCOL>( nNewCol - nMovX );
870 if (nNewCol == (SCsCOL)rCol)
871 bThere = FALSE;
874 if (!bThere)
878 nNewCol = sal::static_int_cast<SCsCOL>( nNewCol + nMovX );
879 bFnd = (nNewCol>=0 && nNewCol<=MAXCOL) ? aCol[nNewCol].HasVisibleDataAt(rRow) : TRUE;
881 while (!bFnd);
884 if (nNewCol<0) nNewCol=0;
885 if (nNewCol>MAXCOL) nNewCol=MAXCOL;
886 rCol = (SCCOL) nNewCol;
889 if (nMovY)
890 aCol[rCol].FindDataAreaPos(rRow,nMovY);
893 BOOL ScTable::ValidNextPos( SCCOL nCol, SCROW nRow, const ScMarkData& rMark,
894 BOOL bMarked, BOOL bUnprotected )
896 if (!ValidCol(nCol) || !ValidRow(nRow))
897 return FALSE;
899 if (pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED))
900 // Skip an overlapped cell.
901 return false;
903 if (bMarked && !rMark.IsCellMarked(nCol,nRow))
904 return FALSE;
906 if (bUnprotected && ((const ScProtectionAttr*)
907 GetAttr(nCol,nRow,ATTR_PROTECTION))->GetProtection())
908 return FALSE;
910 if (bMarked || bUnprotected) //! auch sonst ???
912 // #53697# ausgeblendete muessen uebersprungen werden, weil der Cursor sonst
913 // auf der naechsten Zelle landet, auch wenn die geschuetzt/nicht markiert ist.
914 //! per Extra-Parameter steuern, nur fuer Cursor-Bewegung ???
916 if (RowHidden(nRow))
917 return FALSE;
919 if (ColHidden(nCol))
920 return FALSE;
923 return TRUE;
926 void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
927 BOOL bMarked, BOOL bUnprotected, const ScMarkData& rMark )
929 if (bUnprotected && !IsProtected()) // Tabelle ueberhaupt geschuetzt?
930 bUnprotected = FALSE;
932 USHORT nWrap = 0;
933 SCsCOL nCol = rCol;
934 SCsROW nRow = rRow;
936 nCol = sal::static_int_cast<SCsCOL>( nCol + nMovX );
937 nRow = sal::static_int_cast<SCsROW>( nRow + nMovY );
939 DBG_ASSERT( !nMovY || !bUnprotected,
940 "GetNextPos mit bUnprotected horizontal nicht implementiert" );
942 if ( nMovY && bMarked )
944 BOOL bUp = ( nMovY < 0 );
945 nRow = rMark.GetNextMarked( nCol, nRow, bUp );
946 while ( VALIDROW(nRow) &&
947 (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
949 // #53697# ausgeblendete ueberspringen (s.o.)
950 nRow += nMovY;
951 nRow = rMark.GetNextMarked( nCol, nRow, bUp );
954 while ( nRow < 0 || nRow > MAXROW )
956 nCol = sal::static_int_cast<SCsCOL>( nCol + static_cast<SCsCOL>(nMovY) );
957 while ( VALIDCOL(nCol) && ColHidden(nCol) )
958 nCol = sal::static_int_cast<SCsCOL>( nCol + static_cast<SCsCOL>(nMovY) ); // #53697# skip hidden rows (see above)
959 if (nCol < 0)
961 nCol = MAXCOL;
962 if (++nWrap >= 2)
963 return;
965 else if (nCol > MAXCOL)
967 nCol = 0;
968 if (++nWrap >= 2)
969 return;
971 if (nRow < 0)
972 nRow = MAXROW;
973 else if (nRow > MAXROW)
974 nRow = 0;
975 nRow = rMark.GetNextMarked( nCol, nRow, bUp );
976 while ( VALIDROW(nRow) &&
977 (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
979 // #53697# ausgeblendete ueberspringen (s.o.)
980 nRow += nMovY;
981 nRow = rMark.GetNextMarked( nCol, nRow, bUp );
986 if ( nMovX && ( bMarked || bUnprotected ) )
988 // initiales Weiterzaehlen wrappen:
989 if (nCol<0)
991 nCol = MAXCOL;
992 --nRow;
993 if (nRow<0)
994 nRow = MAXROW;
996 if (nCol>MAXCOL)
998 nCol = 0;
999 ++nRow;
1000 if (nRow>MAXROW)
1001 nRow = 0;
1004 if ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) )
1006 SCsROW* pNextRows = new SCsROW[MAXCOL+1];
1007 SCCOL i;
1009 if ( nMovX > 0 ) // vorwaerts
1011 for (i=0; i<=MAXCOL; i++)
1012 pNextRows[i] = (i<nCol) ? (nRow+1) : nRow;
1015 SCsROW nNextRow = pNextRows[nCol] + 1;
1016 if ( bMarked )
1017 nNextRow = rMark.GetNextMarked( nCol, nNextRow, FALSE );
1018 if ( bUnprotected )
1019 nNextRow = aCol[nCol].GetNextUnprotected( nNextRow, FALSE );
1020 pNextRows[nCol] = nNextRow;
1022 SCsROW nMinRow = MAXROW+1;
1023 for (i=0; i<=MAXCOL; i++)
1024 if (pNextRows[i] < nMinRow) // bei gleichen den linken
1026 nMinRow = pNextRows[i];
1027 nCol = i;
1029 nRow = nMinRow;
1031 if ( nRow > MAXROW )
1033 if (++nWrap >= 2) break; // ungueltigen Wert behalten
1034 nCol = 0;
1035 nRow = 0;
1036 for (i=0; i<=MAXCOL; i++)
1037 pNextRows[i] = 0; // alles ganz von vorne
1040 while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
1042 else // rueckwaerts
1044 for (i=0; i<=MAXCOL; i++)
1045 pNextRows[i] = (i>nCol) ? (nRow-1) : nRow;
1048 SCsROW nNextRow = pNextRows[nCol] - 1;
1049 if ( bMarked )
1050 nNextRow = rMark.GetNextMarked( nCol, nNextRow, TRUE );
1051 if ( bUnprotected )
1052 nNextRow = aCol[nCol].GetNextUnprotected( nNextRow, TRUE );
1053 pNextRows[nCol] = nNextRow;
1055 SCsROW nMaxRow = -1;
1056 for (i=0; i<=MAXCOL; i++)
1057 if (pNextRows[i] >= nMaxRow) // bei gleichen den rechten
1059 nMaxRow = pNextRows[i];
1060 nCol = i;
1062 nRow = nMaxRow;
1064 if ( nRow < 0 )
1066 if (++nWrap >= 2) break; // ungueltigen Wert behalten
1067 nCol = MAXCOL;
1068 nRow = MAXROW;
1069 for (i=0; i<=MAXCOL; i++)
1070 pNextRows[i] = MAXROW; // alles ganz von vorne
1073 while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
1076 delete[] pNextRows;
1080 // ungueltige Werte kommen z.b. bei Tab heraus,
1081 // wenn nicht markiert und nicht geschuetzt ist (linker / rechter Rand),
1082 // dann Werte unveraendert lassen
1084 if (VALIDCOLROW(nCol,nRow))
1086 rCol = nCol;
1087 rRow = nRow;
1091 BOOL ScTable::GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, const ScMarkData& rMark )
1093 const ScMarkArray* pMarkArray = rMark.GetArray();
1094 DBG_ASSERT(pMarkArray,"GetNextMarkedCell ohne MarkArray");
1095 if ( !pMarkArray )
1096 return FALSE;
1098 ++rRow; // naechste Zelle ist gesucht
1100 while ( rCol <= MAXCOL )
1102 const ScMarkArray& rArray = pMarkArray[rCol];
1103 while ( rRow <= MAXROW )
1105 SCROW nStart = (SCROW) rArray.GetNextMarked( (SCsROW) rRow, FALSE );
1106 if ( nStart <= MAXROW )
1108 SCROW nEnd = rArray.GetMarkEnd( nStart, FALSE );
1109 ScColumnIterator aColIter( &aCol[rCol], nStart, nEnd );
1110 SCROW nCellRow;
1111 ScBaseCell* pCell = NULL;
1112 while ( aColIter.Next( nCellRow, pCell ) )
1114 if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
1116 rRow = nCellRow;
1117 return TRUE; // Zelle gefunden
1120 rRow = nEnd + 1; // naechsten markierten Bereich suchen
1122 else
1123 rRow = MAXROW + 1; // Ende der Spalte
1125 rRow = 0;
1126 ++rCol; // naechste Spalte testen
1129 return FALSE; // alle Spalten durch
1132 void ScTable::UpdateDrawRef( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1133 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1134 SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
1136 if ( nTab >= nTab1 && nTab <= nTab2 && nDz == 0 ) // only within the table
1138 InitializeNoteCaptions();
1139 ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
1140 if ( eUpdateRefMode != URM_COPY && pDrawLayer )
1142 if ( eUpdateRefMode == URM_MOVE )
1143 { // source range
1144 nCol1 = sal::static_int_cast<SCCOL>( nCol1 - nDx );
1145 nRow1 = sal::static_int_cast<SCROW>( nRow1 - nDy );
1146 nCol2 = sal::static_int_cast<SCCOL>( nCol2 - nDx );
1147 nRow2 = sal::static_int_cast<SCROW>( nRow2 - nDy );
1149 pDrawLayer->MoveArea( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy,
1150 (eUpdateRefMode == URM_INSDEL) );
1155 void ScTable::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1156 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
1157 ScDocument* pUndoDoc, BOOL bIncludeDraw )
1159 SCCOL i;
1160 SCCOL iMax;
1161 if ( eUpdateRefMode == URM_COPY )
1163 i = nCol1;
1164 iMax = nCol2;
1166 else
1168 i = 0;
1169 iMax = MAXCOL;
1171 for ( ; i<=iMax; i++)
1172 aCol[i].UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
1173 nDx, nDy, nDz, pUndoDoc );
1175 if ( bIncludeDraw )
1176 UpdateDrawRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
1178 if ( nTab >= nTab1 && nTab <= nTab2 && nDz == 0 ) // print ranges: only within the table
1180 SCTAB nSTab = nTab;
1181 SCTAB nETab = nTab;
1182 SCCOL nSCol = 0;
1183 SCROW nSRow = 0;
1184 SCCOL nECol = 0;
1185 SCROW nERow = 0;
1186 BOOL bRecalcPages = FALSE;
1188 for ( ScRangeVec::iterator aIt = aPrintRanges.begin(), aEnd = aPrintRanges.end(); aIt != aEnd; ++aIt )
1190 nSCol = aIt->aStart.Col();
1191 nSRow = aIt->aStart.Row();
1192 nECol = aIt->aEnd.Col();
1193 nERow = aIt->aEnd.Row();
1195 // do not try to modify sheet index of print range
1196 if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1197 nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1198 nDx,nDy,0,
1199 nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1201 *aIt = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1202 bRecalcPages = TRUE;
1206 if ( pRepeatColRange )
1208 nSCol = pRepeatColRange->aStart.Col();
1209 nSRow = pRepeatColRange->aStart.Row();
1210 nECol = pRepeatColRange->aEnd.Col();
1211 nERow = pRepeatColRange->aEnd.Row();
1213 // do not try to modify sheet index of repeat range
1214 if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1215 nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1216 nDx,nDy,0,
1217 nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1219 *pRepeatColRange = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1220 bRecalcPages = TRUE;
1221 nRepeatStartX = nSCol; // fuer UpdatePageBreaks
1222 nRepeatEndX = nECol;
1226 if ( pRepeatRowRange )
1228 nSCol = pRepeatRowRange->aStart.Col();
1229 nSRow = pRepeatRowRange->aStart.Row();
1230 nECol = pRepeatRowRange->aEnd.Col();
1231 nERow = pRepeatRowRange->aEnd.Row();
1233 // do not try to modify sheet index of repeat range
1234 if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1235 nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1236 nDx,nDy,0,
1237 nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1239 *pRepeatRowRange = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1240 bRecalcPages = TRUE;
1241 nRepeatStartY = nSRow; // fuer UpdatePageBreaks
1242 nRepeatEndY = nERow;
1246 // updating print ranges is not necessary with multiple print ranges
1247 if ( bRecalcPages && GetPrintRangeCount() <= 1 )
1249 UpdatePageBreaks(NULL);
1251 SfxObjectShell* pDocSh = pDocument->GetDocumentShell();
1252 if (pDocSh)
1253 pDocSh->Broadcast( ScPaintHint(
1254 ScRange(0,0,nTab,MAXCOL,MAXROW,nTab),
1255 PAINT_GRID ) );
1260 void ScTable::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
1261 ScDocument* pUndoDoc )
1263 for ( SCCOL i=0; i<=MAXCOL; i++ )
1264 aCol[i].UpdateTranspose( rSource, rDest, pUndoDoc );
1267 void ScTable::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1269 for ( SCCOL i=0; i<=MAXCOL; i++ )
1270 aCol[i].UpdateGrow( rArea, nGrowX, nGrowY );
1273 void ScTable::UpdateInsertTab(SCTAB nTable)
1275 if (nTab >= nTable) nTab++;
1276 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].UpdateInsertTab(nTable);
1278 if (IsStreamValid())
1279 SetStreamValid(FALSE);
1282 //UNUSED2008-05 void ScTable::UpdateInsertTabOnlyCells(SCTAB nTable)
1283 //UNUSED2008-05 {
1284 //UNUSED2008-05 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].UpdateInsertTabOnlyCells(nTable);
1285 //UNUSED2008-05 }
1287 void ScTable::UpdateDeleteTab( SCTAB nTable, BOOL bIsMove, ScTable* pRefUndo )
1289 if (nTab > nTable) nTab--;
1291 SCCOL i;
1292 if (pRefUndo)
1293 for (i=0; i <= MAXCOL; i++) aCol[i].UpdateDeleteTab(nTable, bIsMove, &pRefUndo->aCol[i]);
1294 else
1295 for (i=0; i <= MAXCOL; i++) aCol[i].UpdateDeleteTab(nTable, bIsMove, NULL);
1297 if (IsStreamValid())
1298 SetStreamValid(FALSE);
1301 void ScTable::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo,
1302 ScProgress& rProgress )
1304 nTab = nTabNo;
1305 for ( SCCOL i=0; i <= MAXCOL; i++ )
1307 aCol[i].UpdateMoveTab( nOldPos, nNewPos, nTabNo );
1308 rProgress.SetState( rProgress.GetState() + aCol[i].GetCodeCount() );
1311 if (IsStreamValid())
1312 SetStreamValid(FALSE);
1315 void ScTable::UpdateCompile( BOOL bForceIfNameInUse )
1317 for (SCCOL i=0; i <= MAXCOL; i++)
1319 aCol[i].UpdateCompile( bForceIfNameInUse );
1323 void ScTable::SetTabNo(SCTAB nNewTab)
1325 nTab = nNewTab;
1326 for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].SetTabNo(nNewTab);
1329 BOOL ScTable::IsRangeNameInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1330 USHORT nIndex) const
1332 BOOL bInUse = FALSE;
1333 for (SCCOL i = nCol1; !bInUse && (i <= nCol2) && (ValidCol(i)); i++)
1334 bInUse = aCol[i].IsRangeNameInUse(nRow1, nRow2, nIndex);
1335 return bInUse;
1338 void ScTable::FindRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1339 std::set<USHORT>& rIndexes) const
1341 for (SCCOL i = nCol1; i <= nCol2 && ValidCol(i); i++)
1342 aCol[i].FindRangeNamesInUse(nRow1, nRow2, rIndexes);
1345 void ScTable::ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1,
1346 SCCOL nCol2, SCROW nRow2,
1347 const ScRangeData::IndexMap& rMap )
1349 for (SCCOL i = nCol1; i <= nCol2 && (ValidCol(i)); i++)
1351 aCol[i].ReplaceRangeNamesInUse( nRow1, nRow2, rMap );
1355 void ScTable::ExtendPrintArea( OutputDevice* pDev,
1356 SCCOL /* nStartCol */, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1358 if ( !pColFlags || !pRowFlags )
1360 DBG_ERROR("keine ColInfo oder RowInfo in ExtendPrintArea");
1361 return;
1364 Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
1365 double nPPTX = aPix1000.X() / 1000.0;
1366 double nPPTY = aPix1000.Y() / 1000.0;
1368 BOOL bEmpty[MAXCOLCOUNT];
1369 for (SCCOL i=0; i<=MAXCOL; i++)
1370 bEmpty[i] = ( aCol[i].GetCellCount() == 0 );
1372 SCSIZE nIndex;
1373 SCCOL nPrintCol = rEndCol;
1374 for (SCROW nRow = nStartRow; nRow<=nEndRow; nRow++)
1376 if (!RowHidden(nRow))
1378 SCCOL nDataCol = rEndCol;
1379 while (nDataCol > 0 && ( bEmpty[nDataCol] || !aCol[nDataCol].Search(nRow,nIndex) ) )
1380 --nDataCol;
1381 if (!ColHidden(nDataCol))
1383 ScBaseCell* pCell = aCol[nDataCol].GetCell(nRow);
1384 if (pCell)
1386 CellType eType = pCell->GetCellType();
1387 if (eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT
1388 || (eType == CELLTYPE_FORMULA && !((ScFormulaCell*)pCell)->IsValue()) )
1390 BOOL bFormula = FALSE; //! uebergeben
1391 long nPixel = pCell->GetTextWidth();
1393 // Breite bereits im Idle-Handler berechnet?
1394 if ( TEXTWIDTH_DIRTY == nPixel )
1396 ScNeededSizeOptions aOptions;
1397 aOptions.bTotalSize = TRUE;
1398 aOptions.bFormula = bFormula;
1399 aOptions.bSkipMerged = FALSE;
1401 Fraction aZoom(1,1);
1402 nPixel = aCol[nDataCol].GetNeededSize( nRow,
1403 pDev,nPPTX,nPPTY,aZoom,aZoom,
1404 TRUE, aOptions );
1405 pCell->SetTextWidth( (USHORT)nPixel );
1408 long nTwips = (long) (nPixel / nPPTX);
1409 long nDocW = GetColWidth( nDataCol );
1411 long nMissing = nTwips - nDocW;
1412 if ( nMissing > 0 )
1414 // look at alignment
1416 const ScPatternAttr* pPattern = GetPattern( nDataCol, nRow );
1417 const SfxItemSet* pCondSet = NULL;
1418 if ( ((const SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() )
1419 pCondSet = pDocument->GetCondResult( nDataCol, nRow, nTab );
1421 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
1422 pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue();
1423 if ( eHorJust == SVX_HOR_JUSTIFY_CENTER )
1424 nMissing /= 2; // distributed into both directions
1425 else
1427 // STANDARD is LEFT (only text is handled here)
1428 BOOL bRight = ( eHorJust == SVX_HOR_JUSTIFY_RIGHT );
1429 if ( IsLayoutRTL() )
1430 bRight = !bRight;
1431 if ( bRight )
1432 nMissing = 0; // extended only to the left (logical)
1436 SCCOL nCol = nDataCol;
1437 while (nMissing > 0 && nCol < MAXCOL)
1439 ++nCol;
1440 nMissing -= GetColWidth( nCol );
1442 if (nCol>nPrintCol)
1443 nPrintCol = nCol;
1449 rEndCol = nPrintCol;
1452 void ScTable::DoColResize( SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd )
1454 for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
1455 aCol[nCol].Resize(aCol[nCol].GetCellCount() + nAdd);
1458 #define SET_PRINTRANGE( p1, p2 ) \
1459 if ( (p2) ) \
1461 if ( (p1) ) \
1462 *(p1) = *(p2); \
1463 else \
1464 (p1) = new ScRange( *(p2) ); \
1466 else \
1467 DELETEZ( (p1) )
1469 void ScTable::SetRepeatColRange( const ScRange* pNew )
1471 SET_PRINTRANGE( pRepeatColRange, pNew );
1474 void ScTable::SetRepeatRowRange( const ScRange* pNew )
1476 SET_PRINTRANGE( pRepeatRowRange, pNew );
1479 void ScTable::ClearPrintRanges()
1481 aPrintRanges.clear();
1482 bPrintEntireSheet = FALSE;
1485 void ScTable::AddPrintRange( const ScRange& rNew )
1487 bPrintEntireSheet = FALSE;
1488 if( aPrintRanges.size() < 0xFFFF )
1489 aPrintRanges.push_back( rNew );
1492 //UNUSED2009-05 void ScTable::SetPrintRange( const ScRange& rNew )
1493 //UNUSED2009-05 {
1494 //UNUSED2009-05 ClearPrintRanges();
1495 //UNUSED2009-05 AddPrintRange( rNew );
1496 //UNUSED2009-05 }
1498 void ScTable::SetPrintEntireSheet()
1500 if( !IsPrintEntireSheet() )
1502 ClearPrintRanges();
1503 bPrintEntireSheet = TRUE;
1507 const ScRange* ScTable::GetPrintRange(USHORT nPos) const
1509 return (nPos < GetPrintRangeCount()) ? &aPrintRanges[ nPos ] : NULL;
1512 void ScTable::FillPrintSaver( ScPrintSaverTab& rSaveTab ) const
1514 rSaveTab.SetAreas( aPrintRanges, bPrintEntireSheet );
1515 rSaveTab.SetRepeat( pRepeatColRange, pRepeatRowRange );
1518 void ScTable::RestorePrintRanges( const ScPrintSaverTab& rSaveTab )
1520 aPrintRanges = rSaveTab.GetPrintRanges();
1521 bPrintEntireSheet = rSaveTab.IsEntireSheet();
1522 SetRepeatColRange( rSaveTab.GetRepeatCol() );
1523 SetRepeatRowRange( rSaveTab.GetRepeatRow() );
1525 UpdatePageBreaks(NULL);