Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "scitems.hxx"
21 : #include <svx/algitem.hxx>
22 : #include <editeng/justifyitem.hxx>
23 : #include <unotools/textsearch.hxx>
24 : #include <sfx2/objsh.hxx>
25 :
26 : #include "attrib.hxx"
27 : #include "patattr.hxx"
28 : #include "cell.hxx"
29 : #include "table.hxx"
30 : #include "document.hxx"
31 : #include "drwlayer.hxx"
32 : #include "olinetab.hxx"
33 : #include "stlsheet.hxx"
34 : #include "global.hxx"
35 : #include "globstr.hrc"
36 : #include "refupdat.hxx"
37 : #include "markdata.hxx"
38 : #include "progress.hxx"
39 : #include "hints.hxx" // fuer Paint-Broadcast
40 : #include "prnsave.hxx"
41 : #include "tabprotection.hxx"
42 : #include "sheetevents.hxx"
43 : #include "segmenttree.hxx"
44 : #include "dbdata.hxx"
45 : #include "colorscale.hxx"
46 : #include "conditio.hxx"
47 :
48 : #include <vector>
49 :
50 : using ::std::vector;
51 :
52 : namespace {
53 :
54 257 : ScProgress* GetProgressBar(
55 : SCSIZE nCount, SCSIZE nTotalCount, ScProgress* pOuterProgress, ScDocument* pDoc)
56 : {
57 257 : if (nTotalCount < 1000)
58 : {
59 : // if the total number of rows is less than 1000, don't even bother
60 : // with the progress bar because drawing progress bar can be very
61 : // expensive especially in GTK.
62 252 : return NULL;
63 : }
64 :
65 5 : if (pOuterProgress)
66 2 : return pOuterProgress;
67 :
68 3 : if (nCount > 1)
69 : return new ScProgress(
70 3 : pDoc->GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nTotalCount);
71 :
72 0 : return NULL;
73 : }
74 :
75 257 : void GetOptimalHeightsInColumn(
76 : ScColumn* pCol, SCROW nStartRow, SCROW nEndRow, vector<sal_uInt16>& aHeights,
77 : OutputDevice* pDev, double nPPTX, double nPPTY, const Fraction& rZoomX, const Fraction& rZoomY, bool bForce,
78 : ScProgress* pProgress, sal_uInt32 nProgressStart)
79 : {
80 257 : SCSIZE nCount = static_cast<SCSIZE>(nEndRow-nStartRow+1);
81 :
82 : // zuerst einmal ueber den ganzen Bereich
83 : // (mit der letzten Spalte in der Hoffnung, dass die am ehesten noch auf
84 : // Standard formatiert ist)
85 :
86 : pCol[MAXCOL].GetOptimalHeight(
87 257 : nStartRow, nEndRow, &aHeights[0], pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce, 0, 0 );
88 :
89 : // daraus Standardhoehe suchen, die im unteren Bereich gilt
90 :
91 257 : sal_uInt16 nMinHeight = aHeights[nCount-1];
92 257 : SCSIZE nPos = nCount-1;
93 257950273 : while ( nPos && aHeights[nPos-1] >= nMinHeight )
94 257949759 : --nPos;
95 257 : SCROW nMinStart = nStartRow + nPos;
96 :
97 257 : sal_uLong nWeightedCount = 0;
98 263168 : for (SCCOL nCol=0; nCol<MAXCOL; nCol++) // MAXCOL schon oben
99 : {
100 : pCol[nCol].GetOptimalHeight(
101 262911 : nStartRow, nEndRow, &aHeights[0], pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce,
102 525822 : nMinHeight, nMinStart );
103 :
104 262911 : if (pProgress)
105 : {
106 5115 : sal_uLong nWeight = pCol[nCol].GetWeightedCount();
107 5115 : if (nWeight) // nochmal denselben Status muss auch nicht sein
108 : {
109 71 : nWeightedCount += nWeight;
110 71 : pProgress->SetState( nWeightedCount + nProgressStart );
111 : }
112 : }
113 : }
114 257 : }
115 :
116 257 : struct OptimalHeightsFuncObjBase
117 : {
118 257 : virtual ~OptimalHeightsFuncObjBase() {}
119 : virtual bool operator() (SCROW nStartRow, SCROW nEndRow, sal_uInt16 nHeight) = 0;
120 : };
121 :
122 0 : struct SetRowHeightOnlyFunc : public OptimalHeightsFuncObjBase
123 : {
124 : ScTable* mpTab;
125 0 : SetRowHeightOnlyFunc(ScTable* pTab) :
126 0 : mpTab(pTab)
127 0 : {}
128 :
129 0 : virtual bool operator() (SCROW nStartRow, SCROW nEndRow, sal_uInt16 nHeight)
130 : {
131 0 : mpTab->SetRowHeightOnly(nStartRow, nEndRow, nHeight);
132 0 : return false;
133 : }
134 : };
135 :
136 257 : struct SetRowHeightRangeFunc : public OptimalHeightsFuncObjBase
137 : {
138 : ScTable* mpTab;
139 : double mnPPTX;
140 : double mnPPTY;
141 :
142 257 : SetRowHeightRangeFunc(ScTable* pTab, double nPPTX, double nPPTY) :
143 : mpTab(pTab),
144 : mnPPTX(nPPTX),
145 257 : mnPPTY(nPPTY)
146 257 : {}
147 :
148 276 : virtual bool operator() (SCROW nStartRow, SCROW nEndRow, sal_uInt16 nHeight)
149 : {
150 276 : return mpTab->SetRowHeightRange(nStartRow, nEndRow, nHeight, mnPPTX, mnPPTY);
151 : }
152 : };
153 :
154 257 : bool SetOptimalHeightsToRows(OptimalHeightsFuncObjBase& rFuncObj,
155 : ScBitMaskCompressedArray<SCROW, sal_uInt8>* pRowFlags, SCROW nStartRow, SCROW nEndRow, sal_uInt16 nExtra,
156 : const vector<sal_uInt16>& aHeights, bool bForce)
157 : {
158 257 : SCSIZE nCount = static_cast<SCSIZE>(nEndRow-nStartRow+1);
159 257 : bool bChanged = false;
160 257 : SCROW nRngStart = 0;
161 257 : SCROW nRngEnd = 0;
162 257 : sal_uInt16 nLast = 0;
163 514 : for (SCSIZE i=0; i<nCount; i++)
164 : {
165 : size_t nIndex;
166 : SCROW nRegionEndRow;
167 257 : sal_uInt8 nRowFlag = pRowFlags->GetValue( nStartRow+i, nIndex, nRegionEndRow );
168 257 : if ( nRegionEndRow > nEndRow )
169 11 : nRegionEndRow = nEndRow;
170 257 : SCSIZE nMoreRows = nRegionEndRow - ( nStartRow+i ); // additional equal rows after first
171 :
172 257 : bool bAutoSize = ((nRowFlag & CR_MANUALSIZE) == 0);
173 257 : if ( bAutoSize || bForce )
174 : {
175 257 : if (nExtra)
176 : {
177 0 : if (bAutoSize)
178 0 : pRowFlags->SetValue( nStartRow+i, nRegionEndRow, nRowFlag | CR_MANUALSIZE);
179 : }
180 257 : else if (!bAutoSize)
181 0 : pRowFlags->SetValue( nStartRow+i, nRegionEndRow, nRowFlag & ~CR_MANUALSIZE);
182 :
183 257950273 : for (SCSIZE nInner = i; nInner <= i + nMoreRows; ++nInner)
184 : {
185 257950016 : if (nLast)
186 : {
187 257949759 : if (aHeights[nInner]+nExtra == nLast)
188 257949740 : nRngEnd = nStartRow+nInner;
189 : else
190 : {
191 19 : bChanged |= rFuncObj(nRngStart, nRngEnd, nLast);
192 19 : nLast = 0;
193 : }
194 : }
195 257950016 : if (!nLast)
196 : {
197 276 : nLast = aHeights[nInner]+nExtra;
198 276 : nRngStart = nStartRow+nInner;
199 276 : nRngEnd = nStartRow+nInner;
200 : }
201 257 : }
202 : }
203 : else
204 : {
205 0 : if (nLast)
206 0 : bChanged |= rFuncObj(nRngStart, nRngEnd, nLast);
207 0 : nLast = 0;
208 : }
209 257 : i += nMoreRows; // already handled - skip
210 : }
211 257 : if (nLast)
212 257 : bChanged |= rFuncObj(nRngStart, nRngEnd, nLast);
213 :
214 257 : return bChanged;
215 : }
216 :
217 : }
218 :
219 : // -----------------------------------------------------------------------
220 :
221 270 : ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const rtl::OUString& rNewName,
222 : bool bColInfo, bool bRowInfo ) :
223 : aName( rNewName ),
224 : aCodeName( rNewName ),
225 : nLinkMode( 0 ),
226 270 : aPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) ),
227 : nRepeatStartX( SCCOL_REPEAT_NONE ),
228 : nRepeatEndX( SCCOL_REPEAT_NONE ),
229 : nRepeatStartY( SCROW_REPEAT_NONE ),
230 : nRepeatEndY( SCROW_REPEAT_NONE ),
231 : pTabProtection( NULL ),
232 : pColWidth( NULL ),
233 : mpRowHeights( static_cast<ScFlatUInt16RowSegments*>(NULL) ),
234 : pColFlags( NULL ),
235 : pRowFlags( NULL ),
236 270 : mpHiddenCols(new ScFlatBoolColSegments),
237 270 : mpHiddenRows(new ScFlatBoolRowSegments),
238 270 : mpFilteredCols(new ScFlatBoolColSegments),
239 270 : mpFilteredRows(new ScFlatBoolRowSegments),
240 : pOutlineTable( NULL ),
241 : pSheetEvents( NULL ),
242 : nTab( nNewTab ),
243 : pDocument( pDoc ),
244 : pSearchText ( NULL ),
245 : pSortCollator( NULL ),
246 : pRepeatColRange( NULL ),
247 : pRepeatRowRange( NULL ),
248 : nLockCount( 0 ),
249 : pScenarioRanges( NULL ),
250 : aScenarioColor( COL_LIGHTGRAY ),
251 : aTabBgColor( COL_AUTO ),
252 : nScenarioFlags( 0 ),
253 : pDBDataNoName(NULL),
254 : mpRangeName(NULL),
255 0 : mpCondFormatList( new ScConditionalFormatList() ),
256 : maNotes(pDoc),
257 : bScenario(false),
258 : bLayoutRTL(false),
259 : bLoadingRTL(false),
260 : bPageSizeValid(false),
261 : bTableAreaValid(false),
262 : bVisible(true),
263 : bStreamValid(false),
264 : bPendingRowHeights(false),
265 : bCalcNotification(false),
266 : bGlobalKeepQuery(false),
267 : bPrintEntireSheet(true),
268 : bActiveScenario(false),
269 1620 : mbPageBreaksValid(false)
270 : {
271 :
272 270 : if (bColInfo)
273 : {
274 266 : pColWidth = new sal_uInt16[ MAXCOL+1 ];
275 266 : pColFlags = new sal_uInt8[ MAXCOL+1 ];
276 :
277 272650 : for (SCCOL i=0; i<=MAXCOL; i++)
278 : {
279 272384 : pColWidth[i] = STD_COL_WIDTH;
280 272384 : pColFlags[i] = 0;
281 : }
282 : }
283 :
284 270 : if (bRowInfo)
285 : {
286 266 : mpRowHeights.reset(new ScFlatUInt16RowSegments(ScGlobal::nStdRowHeight));
287 266 : pRowFlags = new ScBitMaskCompressedArray< SCROW, sal_uInt8>( MAXROW, 0);
288 : }
289 :
290 270 : if ( pDocument->IsDocVisible() )
291 : {
292 : // when a sheet is added to a visible document,
293 : // initialize its RTL flag from the system locale
294 0 : bLayoutRTL = ScGlobal::IsSystemRTL();
295 : }
296 :
297 270 : ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
298 270 : if (pDrawLayer)
299 : {
300 61 : if ( pDrawLayer->ScAddPage( nTab ) ) // sal_False (not inserted) during Undo
301 : {
302 61 : pDrawLayer->ScRenamePage( nTab, aName );
303 61 : sal_uLong nx = (sal_uLong) ((double) (MAXCOL+1) * STD_COL_WIDTH * HMM_PER_TWIPS );
304 61 : sal_uLong ny = (sal_uLong) ((double) (MAXROW+1) * ScGlobal::nStdRowHeight * HMM_PER_TWIPS );
305 61 : pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( nx, ny ), false );
306 : }
307 : }
308 :
309 276750 : for (SCCOL k=0; k<=MAXCOL; k++)
310 276480 : aCol[k].Init( k, nTab, pDocument );
311 270 : }
312 :
313 205400 : ScTable::~ScTable()
314 : {
315 200 : if (!pDocument->IsInDtorClear())
316 : {
317 : // nicht im dtor die Pages in der falschen Reihenfolge loeschen
318 : // (nTab stimmt dann als Page-Number nicht!)
319 : // In ScDocument::Clear wird hinterher per Clear am Draw Layer alles geloescht.
320 :
321 34 : ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
322 34 : if (pDrawLayer)
323 3 : pDrawLayer->ScRemovePage( nTab );
324 : }
325 :
326 200 : delete[] pColWidth;
327 200 : delete[] pColFlags;
328 200 : delete pRowFlags;
329 200 : delete pSheetEvents;
330 200 : delete pOutlineTable;
331 200 : delete pSearchText;
332 200 : delete pRepeatColRange;
333 200 : delete pRepeatRowRange;
334 200 : delete pScenarioRanges;
335 200 : delete mpRangeName;
336 200 : delete pDBDataNoName;
337 200 : DestroySortCollator();
338 205200 : }
339 :
340 1021 : void ScTable::GetName( rtl::OUString& rName ) const
341 : {
342 1021 : rName = aName;
343 1021 : }
344 :
345 101 : void ScTable::SetName( const rtl::OUString& rNewName )
346 : {
347 101 : aName = rNewName;
348 101 : aUpperName = rtl::OUString(); // invalidated if the name is changed
349 :
350 : // SetStreamValid is handled in ScDocument::RenameTab
351 101 : }
352 :
353 1032 : const rtl::OUString& ScTable::GetUpperName() const
354 : {
355 1032 : if (aUpperName.isEmpty() && !aName.isEmpty())
356 92 : aUpperName = ScGlobal::pCharClass->uppercase(aName);
357 1032 : return aUpperName;
358 : }
359 :
360 9 : void ScTable::SetVisible( bool bVis )
361 : {
362 9 : if (bVisible != bVis && IsStreamValid())
363 0 : SetStreamValid(false);
364 :
365 9 : bVisible = bVis;
366 9 : }
367 :
368 76 : void ScTable::SetStreamValid( bool bSet, bool bIgnoreLock )
369 : {
370 76 : if ( bIgnoreLock || !pDocument->IsStreamValidLocked() )
371 76 : bStreamValid = bSet;
372 76 : }
373 :
374 3 : void ScTable::SetPendingRowHeights( bool bSet )
375 : {
376 3 : bPendingRowHeights = bSet;
377 3 : }
378 :
379 6 : void ScTable::SetLayoutRTL( bool bSet )
380 : {
381 6 : bLayoutRTL = bSet;
382 6 : }
383 :
384 3 : void ScTable::SetLoadingRTL( bool bSet )
385 : {
386 3 : bLoadingRTL = bSet;
387 3 : }
388 :
389 36 : const Color& ScTable::GetTabBgColor() const
390 : {
391 36 : return aTabBgColor;
392 : }
393 :
394 5 : void ScTable::SetTabBgColor(const Color& rColor)
395 : {
396 5 : if (aTabBgColor != rColor)
397 : {
398 : // The tab color has changed. Set this table 'modified'.
399 1 : aTabBgColor = rColor;
400 1 : if (IsStreamValid())
401 0 : SetStreamValid(false);
402 : }
403 5 : }
404 :
405 0 : void ScTable::SetScenario( bool bFlag )
406 : {
407 0 : bScenario = bFlag;
408 0 : }
409 :
410 0 : void ScTable::SetLink( sal_uInt8 nMode,
411 : const String& rDoc, const String& rFlt, const String& rOpt,
412 : const String& rTab, sal_uLong nRefreshDelay )
413 : {
414 0 : nLinkMode = nMode;
415 0 : aLinkDoc = rDoc; // Datei
416 0 : aLinkFlt = rFlt; // Filter
417 0 : aLinkOpt = rOpt; // Filter-Optionen
418 0 : aLinkTab = rTab; // Tabellenname in Quelldatei
419 0 : nLinkRefreshDelay = nRefreshDelay; // refresh delay in seconds, 0==off
420 :
421 0 : if (IsStreamValid())
422 0 : SetStreamValid(false);
423 0 : }
424 :
425 78 : sal_uInt16 ScTable::GetOptimalColWidth( SCCOL nCol, OutputDevice* pDev,
426 : double nPPTX, double nPPTY,
427 : const Fraction& rZoomX, const Fraction& rZoomY,
428 : bool bFormula, const ScMarkData* pMarkData,
429 : const ScColWidthParam* pParam )
430 : {
431 78 : return aCol[nCol].GetOptimalColWidth( pDev, nPPTX, nPPTY, rZoomX, rZoomY,
432 156 : bFormula, STD_COL_WIDTH - STD_EXTRA_WIDTH, pMarkData, pParam );
433 : }
434 :
435 0 : long ScTable::GetNeededSize( SCCOL nCol, SCROW nRow,
436 : OutputDevice* pDev,
437 : double nPPTX, double nPPTY,
438 : const Fraction& rZoomX, const Fraction& rZoomY,
439 : bool bWidth, bool bTotalSize )
440 : {
441 0 : ScNeededSizeOptions aOptions;
442 0 : aOptions.bSkipMerged = false; // zusammengefasste mitzaehlen
443 0 : aOptions.bTotalSize = bTotalSize;
444 :
445 0 : return aCol[nCol].GetNeededSize
446 0 : ( nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, aOptions );
447 : }
448 :
449 1225 : bool ScTable::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nExtra,
450 : OutputDevice* pDev,
451 : double nPPTX, double nPPTY,
452 : const Fraction& rZoomX, const Fraction& rZoomY,
453 : bool bForce, ScProgress* pOuterProgress, sal_uLong nProgressStart )
454 : {
455 : OSL_ENSURE( nExtra==0 || bForce, "autom. OptimalHeight mit Extra" );
456 :
457 1225 : if ( !pDocument->IsAdjustHeightEnabled() )
458 : {
459 968 : return false;
460 : }
461 :
462 257 : SCSIZE nCount = static_cast<SCSIZE>(nEndRow-nStartRow+1);
463 :
464 257 : ScProgress* pProgress = GetProgressBar(nCount, GetWeightedCount(), pOuterProgress, pDocument);
465 :
466 257 : vector<sal_uInt16> aHeights(nCount, 0);
467 :
468 : GetOptimalHeightsInColumn(
469 : aCol, nStartRow, nEndRow, aHeights, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce,
470 257 : pProgress, nProgressStart);
471 :
472 257 : SetRowHeightRangeFunc aFunc(this, nPPTX, nPPTY);
473 : bool bChanged = SetOptimalHeightsToRows(
474 257 : aFunc, pRowFlags, nStartRow, nEndRow, nExtra, aHeights, bForce);
475 :
476 257 : if ( pProgress != pOuterProgress )
477 8 : delete pProgress;
478 :
479 257 : return bChanged;
480 : }
481 :
482 0 : void ScTable::SetOptimalHeightOnly( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nExtra,
483 : OutputDevice* pDev,
484 : double nPPTX, double nPPTY,
485 : const Fraction& rZoomX, const Fraction& rZoomY,
486 : bool bForce, ScProgress* pOuterProgress, sal_uLong nProgressStart )
487 : {
488 : OSL_ENSURE( nExtra==0 || bForce, "autom. OptimalHeight mit Extra" );
489 :
490 0 : if ( !pDocument->IsAdjustHeightEnabled() )
491 0 : return;
492 :
493 0 : SCSIZE nCount = static_cast<SCSIZE>(nEndRow-nStartRow+1);
494 :
495 0 : ScProgress* pProgress = GetProgressBar(nCount, GetWeightedCount(), pOuterProgress, pDocument);
496 :
497 0 : vector<sal_uInt16> aHeights(nCount, 0);
498 :
499 : GetOptimalHeightsInColumn(
500 : aCol, nStartRow, nEndRow, aHeights, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce,
501 0 : pProgress, nProgressStart);
502 :
503 0 : SetRowHeightOnlyFunc aFunc(this);
504 : SetOptimalHeightsToRows(
505 0 : aFunc, pRowFlags, nStartRow, nEndRow, nExtra, aHeights, bForce);
506 :
507 0 : if ( pProgress != pOuterProgress )
508 0 : delete pProgress;
509 : }
510 :
511 9 : bool ScTable::GetCellArea( SCCOL& rEndCol, SCROW& rEndRow ) const
512 : {
513 9 : bool bFound = false;
514 9 : SCCOL nMaxX = 0;
515 9 : SCROW nMaxY = 0;
516 9225 : for (SCCOL i=0; i<=MAXCOL; i++)
517 9216 : if (!aCol[i].IsEmptyVisData())
518 : {
519 67 : bFound = true;
520 67 : nMaxX = i;
521 67 : SCROW nColY = aCol[i].GetLastVisDataPos();
522 67 : if (nColY > nMaxY)
523 8 : nMaxY = nColY;
524 : }
525 :
526 10 : for (ScNotes::const_iterator itr = maNotes.begin(); itr != maNotes.end(); ++itr)
527 : {
528 1 : SCCOL nCol = itr->first.first;
529 1 : SCROW nRow = itr->first.second;
530 :
531 1 : if (nMaxX < nCol)
532 1 : nMaxX = nCol;
533 1 : if (nMaxY < nRow)
534 0 : nMaxY = nRow;
535 : }
536 :
537 9 : rEndCol = nMaxX;
538 9 : rEndRow = nMaxY;
539 9 : return bFound;
540 : }
541 :
542 6 : bool ScTable::GetTableArea( SCCOL& rEndCol, SCROW& rEndRow ) const
543 : {
544 6 : bool bRet = true; //! merken?
545 6 : if (!bTableAreaValid)
546 : {
547 3 : bRet = GetPrintArea(nTableAreaX, nTableAreaY, true);
548 3 : bTableAreaValid = true;
549 : }
550 6 : rEndCol = nTableAreaX;
551 6 : rEndRow = nTableAreaY;
552 6 : return bRet;
553 : }
554 :
555 : const SCCOL SC_COLUMNS_STOP = 30;
556 :
557 78 : bool ScTable::GetPrintArea( SCCOL& rEndCol, SCROW& rEndRow, bool bNotes, bool bFullFormattedArea ) const
558 : {
559 78 : bool bFound = false;
560 78 : SCCOL nMaxX = 0;
561 78 : SCROW nMaxY = 0;
562 : SCCOL i;
563 :
564 79950 : for (i=0; i<=MAXCOL; i++) // Daten testen
565 79872 : if (!aCol[i].IsEmptyVisData())
566 : {
567 75 : bFound = true;
568 75 : if (i>nMaxX)
569 58 : nMaxX = i;
570 75 : SCROW nColY = aCol[i].GetLastVisDataPos();
571 75 : if (nColY > nMaxY)
572 20 : nMaxY = nColY;
573 : }
574 :
575 78 : if (bNotes)
576 : {
577 9 : for (ScNotes::const_iterator itr = maNotes.begin(); itr != maNotes.end(); ++itr)
578 : {
579 0 : SCCOL nCol = itr->first.first;
580 0 : SCROW nRow = itr->first.second;
581 :
582 0 : if (nMaxX < nCol)
583 0 : nMaxX = nCol;
584 0 : if (nMaxY < nRow)
585 0 : nMaxY = nRow;
586 : }
587 : }
588 :
589 78 : SCCOL nMaxDataX = nMaxX;
590 :
591 79950 : for (i=0; i<=MAXCOL; i++) // Attribute testen
592 : {
593 : SCROW nLastRow;
594 79872 : if (aCol[i].GetLastVisibleAttr( nLastRow, bFullFormattedArea ))
595 : {
596 0 : bFound = true;
597 0 : nMaxX = i;
598 0 : if (nLastRow > nMaxY)
599 0 : nMaxY = nLastRow;
600 : }
601 : }
602 :
603 78 : if (nMaxX == MAXCOL) // Attribute rechts weglassen
604 : {
605 0 : --nMaxX;
606 0 : while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1]) )
607 0 : --nMaxX;
608 : }
609 :
610 78 : if ( nMaxX < nMaxDataX )
611 : {
612 0 : nMaxX = nMaxDataX;
613 : }
614 78 : else if ( nMaxX > nMaxDataX )
615 : {
616 0 : SCCOL nAttrStartX = nMaxDataX + 1;
617 0 : while ( nAttrStartX < MAXCOL )
618 : {
619 0 : SCCOL nAttrEndX = nAttrStartX;
620 0 : while ( nAttrEndX < MAXCOL && aCol[nAttrStartX].IsVisibleAttrEqual(aCol[nAttrEndX+1]) )
621 0 : ++nAttrEndX;
622 0 : if ( nAttrEndX + 1 - nAttrStartX >= SC_COLUMNS_STOP )
623 : {
624 : // found equally-formatted columns behind data -> stop before these columns
625 0 : nMaxX = nAttrStartX - 1;
626 :
627 : // also don't include default-formatted columns before that
628 : SCROW nDummyRow;
629 0 : while ( nMaxX > nMaxDataX && !aCol[nMaxX].GetLastVisibleAttr( nDummyRow ) )
630 0 : --nMaxX;
631 : break;
632 : }
633 0 : nAttrStartX = nAttrEndX + 1;
634 : }
635 : }
636 :
637 78 : rEndCol = nMaxX;
638 78 : rEndRow = nMaxY;
639 78 : return bFound;
640 : }
641 :
642 0 : bool ScTable::GetPrintAreaHor( SCROW nStartRow, SCROW nEndRow,
643 : SCCOL& rEndCol, bool /* bNotes */ ) const
644 : {
645 0 : bool bFound = false;
646 0 : SCCOL nMaxX = 0;
647 : SCCOL i;
648 :
649 0 : for (i=0; i<=MAXCOL; i++) // Attribute testen
650 : {
651 0 : if (aCol[i].HasVisibleAttrIn( nStartRow, nEndRow ))
652 : {
653 0 : bFound = true;
654 0 : nMaxX = i;
655 : }
656 : }
657 :
658 0 : if (nMaxX == MAXCOL) // Attribute rechts weglassen
659 : {
660 0 : --nMaxX;
661 0 : while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1], nStartRow, nEndRow) )
662 0 : --nMaxX;
663 : }
664 :
665 0 : for (i=0; i<=MAXCOL; i++) // Daten testen
666 : {
667 0 : if (!aCol[i].IsEmptyBlock( nStartRow, nEndRow )) //! bNotes ??????
668 : {
669 0 : bFound = true;
670 0 : if (i>nMaxX)
671 0 : nMaxX = i;
672 : }
673 : }
674 :
675 0 : rEndCol = nMaxX;
676 0 : return bFound;
677 : }
678 :
679 17 : bool ScTable::GetPrintAreaVer( SCCOL nStartCol, SCCOL nEndCol,
680 : SCROW& rEndRow, bool bNotes ) const
681 : {
682 17 : bool bFound = false;
683 17 : SCROW nMaxY = 0;
684 : SCCOL i;
685 :
686 279 : for (i=nStartCol; i<=nEndCol; i++) // Attribute testen
687 : {
688 : SCROW nLastRow;
689 262 : if (aCol[i].GetLastVisibleAttr( nLastRow ))
690 : {
691 0 : bFound = true;
692 0 : if (nLastRow > nMaxY)
693 0 : nMaxY = nLastRow;
694 : }
695 : }
696 :
697 279 : for (i=nStartCol; i<=nEndCol; i++) // Daten testen
698 262 : if (!aCol[i].IsEmptyVisData())
699 : {
700 61 : bFound = true;
701 61 : SCROW nColY = aCol[i].GetLastVisDataPos();
702 61 : if (nColY > nMaxY)
703 19 : nMaxY = nColY;
704 : }
705 :
706 17 : if (bNotes)
707 : {
708 0 : for (ScNotes::const_iterator itr = maNotes.begin(); itr != maNotes.end(); ++itr)
709 : {
710 0 : SCCOL nCol = itr->first.first;
711 0 : SCROW nRow = itr->first.second;
712 :
713 0 : if (nStartCol > nCol || nEndCol < nCol)
714 0 : continue;
715 :
716 0 : if (nMaxY < nRow)
717 0 : nMaxY = nRow;
718 : }
719 : }
720 :
721 17 : rEndRow = nMaxY;
722 17 : return bFound;
723 : }
724 :
725 6 : bool ScTable::GetDataStart( SCCOL& rStartCol, SCROW& rStartRow ) const
726 : {
727 6 : bool bFound = false;
728 6 : SCCOL nMinX = MAXCOL;
729 6 : SCROW nMinY = MAXROW;
730 : SCCOL i;
731 :
732 6150 : for (i=0; i<=MAXCOL; i++) // Attribute testen
733 : {
734 : SCROW nFirstRow;
735 6144 : if (aCol[i].GetFirstVisibleAttr( nFirstRow ))
736 : {
737 0 : if (!bFound)
738 0 : nMinX = i;
739 0 : bFound = true;
740 0 : if (nFirstRow < nMinY)
741 0 : nMinY = nFirstRow;
742 : }
743 : }
744 :
745 6 : if (nMinX == 0) // Attribute links weglassen
746 : {
747 0 : if ( aCol[0].IsVisibleAttrEqual(aCol[1]) ) // keine einzelnen
748 : {
749 0 : ++nMinX;
750 0 : while ( nMinX<MAXCOL && aCol[nMinX].IsVisibleAttrEqual(aCol[nMinX-1]) )
751 0 : ++nMinX;
752 : }
753 : }
754 :
755 6 : bool bDatFound = false;
756 6150 : for (i=0; i<=MAXCOL; i++) // Daten testen
757 6144 : if (!aCol[i].IsEmptyVisData())
758 : {
759 4 : if (!bDatFound && i<nMinX)
760 4 : nMinX = i;
761 4 : bFound = bDatFound = true;
762 4 : SCROW nColY = aCol[i].GetFirstVisDataPos();
763 4 : if (nColY < nMinY)
764 4 : nMinY = nColY;
765 : }
766 :
767 6 : for (ScNotes::const_iterator itr = maNotes.begin(); itr != maNotes.end(); ++itr)
768 : {
769 0 : bFound = bDatFound = true;
770 0 : SCCOL nCol = itr->first.first;
771 0 : SCROW nRow = itr->first.second;
772 :
773 0 : if (nMinX > nCol)
774 0 : nMinX = nCol;
775 0 : if (nMinY > nRow)
776 0 : nMinY = nRow;
777 : }
778 :
779 6 : rStartCol = nMinX;
780 6 : rStartRow = nMinY;
781 6 : return bFound;
782 : }
783 :
784 5 : void ScTable::GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow,
785 : bool bIncludeOld, bool bOnlyDown ) const
786 : {
787 : // return the smallest area containing at least all contiguous cells having data. This area
788 : // is a square containing also empty cells. It may shrink or extend the area given as input
789 : // Flags as modifiers:
790 : //
791 : // bIncludeOld = true ensure that the returned area contains at least the initial area,
792 : // independently of the emptniess of rows / columns (i.e. does not allow shrinking)
793 : // bOnlyDown = true means extend / shrink the inputed area only down, i.e modifiy only rEndRow
794 :
795 5 : bool bLeft = false;
796 5 : bool bRight = false;
797 5 : bool bTop = false;
798 5 : bool bBottom = false;
799 5 : bool bChanged = false;
800 :
801 31 : do
802 : {
803 31 : bChanged = false;
804 :
805 31 : if (!bOnlyDown)
806 : {
807 31 : SCROW nStart = rStartRow;
808 31 : SCROW nEnd = rEndRow;
809 31 : if (nStart>0) --nStart;
810 31 : if (nEnd<MAXROW) ++nEnd;
811 :
812 31 : if (rEndCol < MAXCOL)
813 31 : if (!aCol[rEndCol+1].IsEmptyBlock(nStart,nEnd))
814 : {
815 12 : ++rEndCol;
816 12 : bChanged = true;
817 12 : bRight = true;
818 : }
819 :
820 31 : if (rStartCol > 0)
821 0 : if (!aCol[rStartCol-1].IsEmptyBlock(nStart,nEnd))
822 : {
823 0 : --rStartCol;
824 0 : bChanged = true;
825 0 : bLeft = true;
826 : }
827 :
828 31 : if (rStartRow > 0)
829 : {
830 0 : SCROW nTest = rStartRow-1;
831 0 : bool needExtend = false;
832 0 : for ( SCCOL i = rStartCol; i<=rEndCol && !needExtend; i++)
833 0 : if (aCol[i].HasDataAt(nTest))
834 0 : needExtend = true;
835 0 : if (needExtend)
836 : {
837 0 : --rStartRow;
838 0 : bChanged = true;
839 0 : bTop = true;
840 : }
841 : }
842 : }
843 :
844 31 : if (rEndRow < MAXROW)
845 : {
846 31 : SCROW nTest = rEndRow+1;
847 31 : bool needExtend = false;
848 74 : for ( SCCOL i = rStartCol; i<=rEndCol && !needExtend; i++)
849 43 : if (aCol[i].HasDataAt(nTest))
850 26 : needExtend = true;
851 31 : if (needExtend)
852 : {
853 26 : ++rEndRow;
854 26 : bChanged = true;
855 26 : bBottom = true;
856 : }
857 : }
858 : }
859 : while( bChanged );
860 :
861 5 : if ( !bIncludeOld && !bOnlyDown )
862 : {
863 0 : if ( !bLeft )
864 0 : while ( aCol[rStartCol].IsEmptyBlock(rStartRow,rEndRow) && rStartCol < MAXCOL && rStartCol < rEndCol)
865 0 : ++rStartCol;
866 :
867 0 : if ( !bRight )
868 0 : while ( aCol[rEndCol].IsEmptyBlock(rStartRow,rEndRow) && rEndCol > 0 && rStartCol < rEndCol)
869 0 : --rEndCol;
870 :
871 0 : if ( !bTop && rStartRow < MAXROW && rStartRow < rEndRow )
872 : {
873 0 : bool shrink = true;
874 0 : do
875 : {
876 0 : for ( SCCOL i = rStartCol; i<=rEndCol && shrink; i++)
877 0 : if (aCol[i].HasDataAt(rStartRow))
878 0 : shrink = false;
879 0 : if (shrink)
880 0 : ++rStartRow;
881 : }while( shrink && rStartRow < MAXROW && rStartRow < rEndRow);
882 : }
883 : }
884 :
885 5 : if ( !bIncludeOld )
886 : {
887 0 : if ( !bBottom && rEndRow > 0 && rStartRow < rEndRow )
888 : {
889 0 : bool shrink = true;
890 0 : do
891 : {
892 0 : for ( SCCOL i = rStartCol; i<=rEndCol && shrink; i++)
893 0 : if (aCol[i].HasDataAt(rEndRow))
894 0 : shrink = false;
895 0 : if (shrink)
896 0 : --rEndRow;
897 : }while( shrink && rEndRow > 0 && rStartRow < rEndRow );
898 : }
899 : }
900 5 : }
901 :
902 :
903 6 : bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow,
904 : SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const
905 : {
906 6 : o_bShrunk = false;
907 :
908 6 : PutInOrder( rStartCol, rEndCol);
909 6 : PutInOrder( rStartRow, rEndRow);
910 6 : if (rStartCol < 0)
911 0 : rStartCol = 0, o_bShrunk = true;
912 6 : if (rStartRow < 0)
913 0 : rStartRow = 0, o_bShrunk = true;
914 6 : if (rEndCol > MAXCOL)
915 0 : rEndCol = MAXCOL, o_bShrunk = true;
916 6 : if (rEndRow > MAXROW)
917 0 : rEndRow = MAXROW, o_bShrunk = true;
918 :
919 : bool bChanged;
920 9 : do
921 : {
922 9 : bChanged = false;
923 :
924 18 : while (rStartCol < rEndCol)
925 : {
926 0 : if (aCol[rEndCol].IsEmptyBlock( rStartRow, rEndRow))
927 : {
928 0 : --rEndCol;
929 0 : bChanged = true;
930 : }
931 : else
932 0 : break; // while
933 : }
934 :
935 18 : while (rStartCol < rEndCol)
936 : {
937 0 : if (aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow))
938 : {
939 0 : ++rStartCol;
940 0 : bChanged = true;
941 : }
942 : else
943 0 : break; // while
944 : }
945 :
946 9 : if (!bColumnsOnly)
947 : {
948 9 : if (rStartRow < rEndRow)
949 : {
950 9 : bool bFound = false;
951 18 : for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++)
952 9 : if (aCol[i].HasDataAt( rStartRow))
953 6 : bFound = true;
954 9 : if (!bFound)
955 : {
956 3 : ++rStartRow;
957 3 : bChanged = true;
958 : }
959 : }
960 :
961 9 : if (rStartRow < rEndRow)
962 : {
963 9 : bool bFound = false;
964 18 : for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++)
965 9 : if (aCol[i].HasDataAt( rEndRow))
966 9 : bFound = true;
967 9 : if (!bFound)
968 : {
969 0 : --rEndRow;
970 0 : bChanged = true;
971 : }
972 : }
973 : }
974 :
975 9 : if (bChanged)
976 3 : o_bShrunk = true;
977 : } while( bChanged );
978 :
979 : return rStartCol != rEndCol || (bColumnsOnly ?
980 0 : !aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow) :
981 6 : (rStartRow != rEndRow || aCol[rStartCol].HasDataAt( rStartRow)));
982 : }
983 :
984 :
985 2 : SCSIZE ScTable::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow,
986 : SCCOL nEndCol, SCROW nEndRow, ScDirection eDir ) const
987 : {
988 2 : SCSIZE nCount = 0;
989 : SCCOL nCol;
990 2 : if ((eDir == DIR_BOTTOM) || (eDir == DIR_TOP))
991 : {
992 0 : nCount = static_cast<SCSIZE>(nEndRow - nStartRow);
993 0 : for (nCol = nStartCol; nCol <= nEndCol; nCol++)
994 0 : nCount = Min(nCount, aCol[nCol].GetEmptyLinesInBlock(nStartRow, nEndRow, eDir));
995 : }
996 2 : else if (eDir == DIR_RIGHT)
997 : {
998 2 : nCol = nEndCol;
999 4084 : while (((SCsCOL)nCol >= (SCsCOL)nStartCol) &&
1000 2040 : aCol[nCol].IsEmptyBlock(nStartRow, nEndRow))
1001 : {
1002 2040 : nCount++;
1003 2040 : nCol--;
1004 : }
1005 : }
1006 : else
1007 : {
1008 0 : nCol = nStartCol;
1009 0 : while ((nCol <= nEndCol) && aCol[nCol].IsEmptyBlock(nStartRow, nEndRow))
1010 : {
1011 0 : nCount++;
1012 0 : nCol++;
1013 : }
1014 : }
1015 2 : return nCount;
1016 : }
1017 :
1018 0 : bool ScTable::IsEmptyLine( SCROW nRow, SCCOL nStartCol, SCCOL nEndCol ) const
1019 : {
1020 0 : bool bFound = false;
1021 0 : for (SCCOL i=nStartCol; i<=nEndCol && !bFound; i++)
1022 0 : if (aCol[i].HasDataAt(nRow))
1023 0 : bFound = true;
1024 0 : return !bFound;
1025 : }
1026 :
1027 0 : void ScTable::LimitChartArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow ) const
1028 : {
1029 0 : while ( rStartCol<rEndCol && aCol[rStartCol].IsEmptyBlock(rStartRow,rEndRow) )
1030 0 : ++rStartCol;
1031 :
1032 0 : while ( rStartCol<rEndCol && aCol[rEndCol].IsEmptyBlock(rStartRow,rEndRow) )
1033 0 : --rEndCol;
1034 :
1035 0 : while ( rStartRow<rEndRow && IsEmptyLine(rStartRow, rStartCol, rEndCol) )
1036 0 : ++rStartRow;
1037 :
1038 0 : while ( rStartRow<rEndRow && IsEmptyLine(rEndRow, rStartCol, rEndCol) )
1039 0 : --rEndRow;
1040 0 : }
1041 :
1042 9 : SCCOL ScTable::FindNextVisibleCol( SCCOL nCol, bool bRight ) const
1043 : {
1044 9 : if(bRight)
1045 : {
1046 9 : nCol++;
1047 9 : SCCOL nEnd = 0;
1048 9 : bool bHidden = pDocument->ColHidden(nCol, nTab, NULL, &nEnd);
1049 9 : if(bHidden)
1050 2 : nCol = nEnd +1;
1051 :
1052 9 : return std::min<SCCOL>(MAXCOL, nCol);
1053 : }
1054 : else
1055 : {
1056 0 : nCol--;
1057 0 : SCCOL nStart = MAXCOL;
1058 0 : bool bHidden = pDocument->ColHidden(nCol, nTab, &nStart, NULL);
1059 0 : if(bHidden)
1060 0 : nCol = nStart - 1;
1061 :
1062 0 : return std::max<SCCOL>(0, nCol);
1063 : }
1064 : }
1065 :
1066 4 : SCCOL ScTable::FindNextVisibleColWithContent( SCCOL nCol, bool bRight, SCROW nRow ) const
1067 : {
1068 4 : if(bRight)
1069 : {
1070 4 : if(nCol == MAXCOL)
1071 0 : return MAXCOL;
1072 :
1073 1019 : do
1074 : {
1075 1022 : nCol++;
1076 1022 : SCCOL nEndCol = 0;
1077 1022 : bool bHidden = pDocument->ColHidden( nCol, nTab, NULL, &nEndCol );
1078 1022 : if(bHidden)
1079 : {
1080 2 : nCol = nEndCol +1;
1081 2 : if(nEndCol >= MAXCOL)
1082 0 : return MAXCOL;
1083 : }
1084 :
1085 1022 : if(aCol[nCol].HasVisibleDataAt(nRow))
1086 3 : return nCol;
1087 : }
1088 : while(nCol < MAXCOL);
1089 :
1090 1 : return MAXCOL;
1091 : }
1092 : else
1093 : {
1094 0 : if(nCol == 0)
1095 0 : return 0;
1096 :
1097 0 : do
1098 : {
1099 0 : nCol--;
1100 0 : SCCOL nStartCol = MAXCOL;
1101 0 : bool bHidden = pDocument->ColHidden( nCol, nTab, &nStartCol, NULL );
1102 0 : if(bHidden)
1103 : {
1104 0 : nCol = nStartCol -1;
1105 0 : if(nCol <= 0)
1106 0 : return 0;
1107 : }
1108 :
1109 0 : if(aCol[nCol].HasVisibleDataAt(nRow))
1110 0 : return nCol;
1111 : }
1112 : while(nCol > 0);
1113 :
1114 0 : return 0;
1115 : }
1116 : }
1117 :
1118 14 : void ScTable::FindAreaPos( SCCOL& rCol, SCROW& rRow, ScMoveDirection eDirection ) const
1119 : {
1120 14 : if (eDirection == SC_MOVE_LEFT || eDirection == SC_MOVE_RIGHT)
1121 : {
1122 7 : SCCOL nNewCol = rCol;
1123 7 : bool bThere = aCol[nNewCol].HasVisibleDataAt(rRow);
1124 7 : bool bRight = (eDirection == SC_MOVE_RIGHT);
1125 7 : if (bThere)
1126 : {
1127 6 : if(nNewCol >= MAXCOL && eDirection == SC_MOVE_RIGHT)
1128 0 : return;
1129 6 : else if(nNewCol == 0 && eDirection == SC_MOVE_LEFT)
1130 0 : return;
1131 :
1132 6 : SCCOL nNextCol = FindNextVisibleCol( nNewCol, bRight );
1133 :
1134 6 : if(aCol[nNextCol].HasVisibleDataAt(rRow))
1135 : {
1136 3 : bool bFound = false;
1137 3 : nNewCol = nNextCol;
1138 3 : do
1139 : {
1140 3 : nNextCol = FindNextVisibleCol( nNewCol, bRight );
1141 3 : if(aCol[nNextCol].HasVisibleDataAt(rRow))
1142 0 : nNewCol = nNextCol;
1143 : else
1144 3 : bFound = true;
1145 : }
1146 3 : while(!bFound && nNextCol > 0 && nNextCol < MAXCOL);
1147 : }
1148 : else
1149 : {
1150 3 : nNewCol = FindNextVisibleColWithContent(nNewCol, bRight, rRow);
1151 : }
1152 : }
1153 : else
1154 : {
1155 1 : nNewCol = FindNextVisibleColWithContent(nNewCol, bRight, rRow);
1156 : }
1157 :
1158 7 : if (nNewCol<0)
1159 0 : nNewCol=0;
1160 7 : if (nNewCol>MAXCOL)
1161 0 : nNewCol=MAXCOL;
1162 7 : rCol = nNewCol;
1163 : }
1164 : else
1165 : {
1166 7 : aCol[rCol].FindDataAreaPos(rRow,eDirection == SC_MOVE_DOWN);
1167 : }
1168 : }
1169 :
1170 0 : bool ScTable::ValidNextPos( SCCOL nCol, SCROW nRow, const ScMarkData& rMark,
1171 : bool bMarked, bool bUnprotected ) const
1172 : {
1173 0 : if (!ValidCol(nCol) || !ValidRow(nRow))
1174 0 : return false;
1175 :
1176 0 : if (pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED))
1177 : // Skip an overlapped cell.
1178 0 : return false;
1179 :
1180 0 : if (bMarked && !rMark.IsCellMarked(nCol,nRow))
1181 0 : return false;
1182 :
1183 0 : if (bUnprotected && ((const ScProtectionAttr*)
1184 0 : GetAttr(nCol,nRow,ATTR_PROTECTION))->GetProtection())
1185 0 : return false;
1186 :
1187 0 : if (bMarked || bUnprotected) //! auch sonst ???
1188 : {
1189 : // ausgeblendete muessen uebersprungen werden, weil der Cursor sonst
1190 : // auf der naechsten Zelle landet, auch wenn die geschuetzt/nicht markiert ist.
1191 : //! per Extra-Parameter steuern, nur fuer Cursor-Bewegung ???
1192 :
1193 0 : if (RowHidden(nRow))
1194 0 : return false;
1195 :
1196 0 : if (ColHidden(nCol))
1197 0 : return false;
1198 : }
1199 :
1200 0 : return true;
1201 : }
1202 :
1203 0 : void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
1204 : bool bMarked, bool bUnprotected, const ScMarkData& rMark ) const
1205 : {
1206 0 : if (bUnprotected && !IsProtected()) // Tabelle ueberhaupt geschuetzt?
1207 0 : bUnprotected = false;
1208 :
1209 0 : sal_uInt16 nWrap = 0;
1210 0 : SCsCOL nCol = rCol;
1211 0 : SCsROW nRow = rRow;
1212 :
1213 0 : nCol = sal::static_int_cast<SCsCOL>( nCol + nMovX );
1214 0 : nRow = sal::static_int_cast<SCsROW>( nRow + nMovY );
1215 :
1216 : OSL_ENSURE( !nMovY || !bUnprotected,
1217 : "GetNextPos mit bUnprotected horizontal nicht implementiert" );
1218 :
1219 0 : if ( nMovY && bMarked )
1220 : {
1221 0 : bool bUp = ( nMovY < 0 );
1222 0 : nRow = rMark.GetNextMarked( nCol, nRow, bUp );
1223 0 : while ( VALIDROW(nRow) &&
1224 0 : (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
1225 : {
1226 : // ausgeblendete ueberspringen (s.o.)
1227 0 : nRow += nMovY;
1228 0 : nRow = rMark.GetNextMarked( nCol, nRow, bUp );
1229 : }
1230 :
1231 0 : while ( nRow < 0 || nRow > MAXROW )
1232 : {
1233 0 : nCol = sal::static_int_cast<SCsCOL>( nCol + static_cast<SCsCOL>(nMovY) );
1234 0 : while ( VALIDCOL(nCol) && ColHidden(nCol) )
1235 0 : nCol = sal::static_int_cast<SCsCOL>( nCol + static_cast<SCsCOL>(nMovY) ); // skip hidden rows (see above)
1236 0 : if (nCol < 0)
1237 : {
1238 0 : nCol = MAXCOL;
1239 0 : if (++nWrap >= 2)
1240 0 : return;
1241 : }
1242 0 : else if (nCol > MAXCOL)
1243 : {
1244 0 : nCol = 0;
1245 0 : if (++nWrap >= 2)
1246 0 : return;
1247 : }
1248 0 : if (nRow < 0)
1249 0 : nRow = MAXROW;
1250 0 : else if (nRow > MAXROW)
1251 0 : nRow = 0;
1252 0 : nRow = rMark.GetNextMarked( nCol, nRow, bUp );
1253 0 : while ( VALIDROW(nRow) &&
1254 0 : (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
1255 : {
1256 : // ausgeblendete ueberspringen (s.o.)
1257 0 : nRow += nMovY;
1258 0 : nRow = rMark.GetNextMarked( nCol, nRow, bUp );
1259 : }
1260 : }
1261 : }
1262 :
1263 0 : if ( nMovX && ( bMarked || bUnprotected ) )
1264 : {
1265 : // initiales Weiterzaehlen wrappen:
1266 0 : if (nCol<0)
1267 : {
1268 0 : nCol = MAXCOL;
1269 0 : --nRow;
1270 0 : if (nRow<0)
1271 0 : nRow = MAXROW;
1272 : }
1273 0 : if (nCol>MAXCOL)
1274 : {
1275 0 : nCol = 0;
1276 0 : ++nRow;
1277 0 : if (nRow>MAXROW)
1278 0 : nRow = 0;
1279 : }
1280 :
1281 0 : if ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) )
1282 : {
1283 0 : SCsROW* pNextRows = new SCsROW[MAXCOL+1];
1284 : SCCOL i;
1285 :
1286 0 : if ( nMovX > 0 ) // vorwaerts
1287 : {
1288 0 : for (i=0; i<=MAXCOL; i++)
1289 0 : pNextRows[i] = (i<nCol) ? (nRow+1) : nRow;
1290 0 : do
1291 : {
1292 0 : SCsROW nNextRow = pNextRows[nCol] + 1;
1293 0 : if ( bMarked )
1294 0 : nNextRow = rMark.GetNextMarked( nCol, nNextRow, false );
1295 0 : if ( bUnprotected )
1296 0 : nNextRow = aCol[nCol].GetNextUnprotected( nNextRow, false );
1297 0 : pNextRows[nCol] = nNextRow;
1298 :
1299 0 : SCsROW nMinRow = MAXROW+1;
1300 0 : for (i=0; i<=MAXCOL; i++)
1301 0 : if (pNextRows[i] < nMinRow) // bei gleichen den linken
1302 : {
1303 0 : nMinRow = pNextRows[i];
1304 0 : nCol = i;
1305 : }
1306 0 : nRow = nMinRow;
1307 :
1308 0 : if ( nRow > MAXROW )
1309 : {
1310 0 : if (++nWrap >= 2) break; // ungueltigen Wert behalten
1311 0 : nCol = 0;
1312 0 : nRow = 0;
1313 0 : for (i=0; i<=MAXCOL; i++)
1314 0 : pNextRows[i] = 0; // alles ganz von vorne
1315 : }
1316 : }
1317 0 : while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
1318 : }
1319 : else // rueckwaerts
1320 : {
1321 0 : for (i=0; i<=MAXCOL; i++)
1322 0 : pNextRows[i] = (i>nCol) ? (nRow-1) : nRow;
1323 0 : do
1324 : {
1325 0 : SCsROW nNextRow = pNextRows[nCol] - 1;
1326 0 : if ( bMarked )
1327 0 : nNextRow = rMark.GetNextMarked( nCol, nNextRow, true );
1328 0 : if ( bUnprotected )
1329 0 : nNextRow = aCol[nCol].GetNextUnprotected( nNextRow, true );
1330 0 : pNextRows[nCol] = nNextRow;
1331 :
1332 0 : SCsROW nMaxRow = -1;
1333 0 : for (i=0; i<=MAXCOL; i++)
1334 0 : if (pNextRows[i] >= nMaxRow) // bei gleichen den rechten
1335 : {
1336 0 : nMaxRow = pNextRows[i];
1337 0 : nCol = i;
1338 : }
1339 0 : nRow = nMaxRow;
1340 :
1341 0 : if ( nRow < 0 )
1342 : {
1343 0 : if (++nWrap >= 2) break; // ungueltigen Wert behalten
1344 0 : nCol = MAXCOL;
1345 0 : nRow = MAXROW;
1346 0 : for (i=0; i<=MAXCOL; i++)
1347 0 : pNextRows[i] = MAXROW; // alles ganz von vorne
1348 : }
1349 : }
1350 0 : while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
1351 : }
1352 :
1353 0 : delete[] pNextRows;
1354 : }
1355 : }
1356 :
1357 : // ungueltige Werte kommen z.b. bei Tab heraus,
1358 : // wenn nicht markiert und nicht geschuetzt ist (linker / rechter Rand),
1359 : // dann Werte unveraendert lassen
1360 :
1361 0 : if (VALIDCOLROW(nCol,nRow))
1362 : {
1363 0 : rCol = nCol;
1364 0 : rRow = nRow;
1365 : }
1366 : }
1367 :
1368 0 : bool ScTable::GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, const ScMarkData& rMark ) const
1369 : {
1370 0 : const ScMarkArray* pMarkArray = rMark.GetArray();
1371 : OSL_ENSURE(pMarkArray,"GetNextMarkedCell ohne MarkArray");
1372 0 : if ( !pMarkArray )
1373 0 : return false;
1374 :
1375 0 : ++rRow; // naechste Zelle ist gesucht
1376 :
1377 0 : while ( rCol <= MAXCOL )
1378 : {
1379 0 : const ScMarkArray& rArray = pMarkArray[rCol];
1380 0 : while ( rRow <= MAXROW )
1381 : {
1382 0 : SCROW nStart = (SCROW) rArray.GetNextMarked( (SCsROW) rRow, false );
1383 0 : if ( nStart <= MAXROW )
1384 : {
1385 0 : SCROW nEnd = rArray.GetMarkEnd( nStart, false );
1386 0 : ScColumnIterator aColIter( &aCol[rCol], nStart, nEnd );
1387 : SCROW nCellRow;
1388 0 : ScBaseCell* pCell = NULL;
1389 0 : while ( aColIter.Next( nCellRow, pCell ) )
1390 : {
1391 0 : if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
1392 : {
1393 0 : rRow = nCellRow;
1394 0 : return true; // Zelle gefunden
1395 : }
1396 : }
1397 0 : rRow = nEnd + 1; // naechsten markierten Bereich suchen
1398 : }
1399 : else
1400 0 : rRow = MAXROW + 1; // Ende der Spalte
1401 : }
1402 0 : rRow = 0;
1403 0 : ++rCol; // naechste Spalte testen
1404 : }
1405 :
1406 0 : return false; // alle Spalten durch
1407 : }
1408 :
1409 19 : void ScTable::UpdateDrawRef( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1410 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1411 : SCsCOL nDx, SCsROW nDy, SCsTAB nDz, bool bUpdateNoteCaptionPos )
1412 : {
1413 19 : if ( nTab >= nTab1 && nTab <= nTab2 && nDz == 0 ) // only within the table
1414 : {
1415 16 : InitializeNoteCaptions();
1416 16 : ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
1417 16 : if ( eUpdateRefMode != URM_COPY && pDrawLayer )
1418 : {
1419 4 : if ( eUpdateRefMode == URM_MOVE )
1420 : { // source range
1421 0 : nCol1 = sal::static_int_cast<SCCOL>( nCol1 - nDx );
1422 0 : nRow1 = sal::static_int_cast<SCROW>( nRow1 - nDy );
1423 0 : nCol2 = sal::static_int_cast<SCCOL>( nCol2 - nDx );
1424 0 : nRow2 = sal::static_int_cast<SCROW>( nRow2 - nDy );
1425 : }
1426 : pDrawLayer->MoveArea( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy,
1427 4 : (eUpdateRefMode == URM_INSDEL), bUpdateNoteCaptionPos );
1428 : }
1429 : }
1430 19 : }
1431 :
1432 25 : void ScTable::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1433 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
1434 : ScDocument* pUndoDoc, bool bIncludeDraw, bool bUpdateNoteCaptionPos )
1435 : {
1436 25 : bool bUpdated = false;
1437 : SCCOL i;
1438 : SCCOL iMax;
1439 25 : if ( eUpdateRefMode == URM_COPY )
1440 : {
1441 6 : i = nCol1;
1442 6 : iMax = nCol2;
1443 : }
1444 : else
1445 : {
1446 19 : i = 0;
1447 19 : iMax = MAXCOL;
1448 : }
1449 :
1450 : // Named expressions need to be updated before formulas acessing them.
1451 25 : if (mpRangeName)
1452 : {
1453 1 : ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );;
1454 1 : mpRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, true );
1455 : }
1456 :
1457 22558 : for ( ; i<=iMax; i++)
1458 22533 : bUpdated |= aCol[i].UpdateReference(
1459 45066 : eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz, pUndoDoc );
1460 :
1461 25 : if ( bIncludeDraw )
1462 13 : UpdateDrawRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz, bUpdateNoteCaptionPos );
1463 :
1464 25 : if ( nTab >= nTab1 && nTab <= nTab2 && nDz == 0 ) // print ranges: only within the table
1465 : {
1466 17 : SCTAB nSTab = nTab;
1467 17 : SCTAB nETab = nTab;
1468 17 : SCCOL nSCol = 0;
1469 17 : SCROW nSRow = 0;
1470 17 : SCCOL nECol = 0;
1471 17 : SCROW nERow = 0;
1472 17 : bool bRecalcPages = false;
1473 :
1474 17 : for ( ScRangeVec::iterator aIt = aPrintRanges.begin(), aEnd = aPrintRanges.end(); aIt != aEnd; ++aIt )
1475 : {
1476 0 : nSCol = aIt->aStart.Col();
1477 0 : nSRow = aIt->aStart.Row();
1478 0 : nECol = aIt->aEnd.Col();
1479 0 : nERow = aIt->aEnd.Row();
1480 :
1481 : // do not try to modify sheet index of print range
1482 0 : if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1483 : nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1484 : nDx,nDy,0,
1485 0 : nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1486 : {
1487 0 : *aIt = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1488 0 : bRecalcPages = true;
1489 : }
1490 : }
1491 :
1492 17 : if ( pRepeatColRange )
1493 : {
1494 0 : nSCol = pRepeatColRange->aStart.Col();
1495 0 : nSRow = pRepeatColRange->aStart.Row();
1496 0 : nECol = pRepeatColRange->aEnd.Col();
1497 0 : nERow = pRepeatColRange->aEnd.Row();
1498 :
1499 : // do not try to modify sheet index of repeat range
1500 0 : if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1501 : nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1502 : nDx,nDy,0,
1503 0 : nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1504 : {
1505 0 : *pRepeatColRange = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1506 0 : bRecalcPages = true;
1507 0 : nRepeatStartX = nSCol; // fuer UpdatePageBreaks
1508 0 : nRepeatEndX = nECol;
1509 : }
1510 : }
1511 :
1512 17 : if ( pRepeatRowRange )
1513 : {
1514 0 : nSCol = pRepeatRowRange->aStart.Col();
1515 0 : nSRow = pRepeatRowRange->aStart.Row();
1516 0 : nECol = pRepeatRowRange->aEnd.Col();
1517 0 : nERow = pRepeatRowRange->aEnd.Row();
1518 :
1519 : // do not try to modify sheet index of repeat range
1520 0 : if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1521 : nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1522 : nDx,nDy,0,
1523 0 : nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1524 : {
1525 0 : *pRepeatRowRange = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1526 0 : bRecalcPages = true;
1527 0 : nRepeatStartY = nSRow; // fuer UpdatePageBreaks
1528 0 : nRepeatEndY = nERow;
1529 : }
1530 : }
1531 :
1532 : // updating print ranges is not necessary with multiple print ranges
1533 17 : if ( bRecalcPages && GetPrintRangeCount() <= 1 )
1534 : {
1535 0 : UpdatePageBreaks(NULL);
1536 :
1537 0 : pDocument->RepaintRange( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab) );
1538 : }
1539 : }
1540 :
1541 25 : if (bUpdated && IsStreamValid())
1542 2 : SetStreamValid(false);
1543 :
1544 25 : if(mpCondFormatList)
1545 25 : mpCondFormatList->UpdateReference( eUpdateRefMode, ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2), nDx, nDy, nDz);
1546 25 : }
1547 :
1548 0 : void ScTable::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
1549 : ScDocument* pUndoDoc )
1550 : {
1551 0 : for ( SCCOL i=0; i<=MAXCOL; i++ )
1552 0 : aCol[i].UpdateTranspose( rSource, rDest, pUndoDoc );
1553 0 : }
1554 :
1555 0 : void ScTable::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1556 : {
1557 0 : for ( SCCOL i=0; i<=MAXCOL; i++ )
1558 0 : aCol[i].UpdateGrow( rArea, nGrowX, nGrowY );
1559 0 : }
1560 :
1561 24 : void ScTable::UpdateInsertTab(SCTAB nTable, SCTAB nNewSheets)
1562 : {
1563 24 : if (nTab >= nTable)
1564 : {
1565 17 : nTab += nNewSheets;
1566 17 : if (pDBDataNoName)
1567 0 : pDBDataNoName->UpdateMoveTab(nTab - 1 ,nTab);
1568 : }
1569 24 : for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].UpdateInsertTab(nTable, nNewSheets);
1570 :
1571 24 : if (mpRangeName)
1572 0 : mpRangeName->UpdateTabRef( nTable, 1, 0, nNewSheets);
1573 :
1574 24 : if (mpRangeName)
1575 0 : mpRangeName->UpdateTabRef( nTable, 1);
1576 :
1577 24 : if (IsStreamValid())
1578 0 : SetStreamValid(false);
1579 :
1580 24 : if(mpCondFormatList)
1581 24 : mpCondFormatList->UpdateReference( URM_INSDEL, ScRange(0,0, nTable, MAXCOL, MAXROW, nTable+nNewSheets-1),0,0, nNewSheets);
1582 24 : }
1583 :
1584 79 : void ScTable::UpdateDeleteTab( SCTAB nTable, bool bIsMove, ScTable* pRefUndo, SCTAB nSheets )
1585 : {
1586 79 : if (nTab > nTable)
1587 : {
1588 13 : nTab -= nSheets;
1589 13 : if (pDBDataNoName)
1590 0 : pDBDataNoName->UpdateMoveTab(nTab + 1,nTab);
1591 : }
1592 :
1593 : SCCOL i;
1594 79 : if (pRefUndo)
1595 0 : for (i=0; i <= MAXCOL; i++) aCol[i].UpdateDeleteTab(nTable, bIsMove, &pRefUndo->aCol[i], nSheets);
1596 : else
1597 79 : for (i=0; i <= MAXCOL; i++) aCol[i].UpdateDeleteTab(nTable, bIsMove, NULL, nSheets);
1598 :
1599 79 : if (mpRangeName)
1600 : {
1601 4 : for (SCTAB aTab = 0; aTab < nSheets; ++aTab)
1602 : {
1603 2 : mpRangeName->UpdateTabRef( nTable + aTab, 2 );
1604 : }
1605 : }
1606 :
1607 79 : if (mpRangeName)
1608 : {
1609 2 : mpRangeName->UpdateTabRef( nTable, 2 );
1610 : }
1611 :
1612 79 : if (IsStreamValid())
1613 1 : SetStreamValid(false);
1614 :
1615 79 : if(mpCondFormatList)
1616 79 : mpCondFormatList->UpdateReference( URM_INSDEL, ScRange(0,0, nTable, MAXCOL, MAXROW, nTable+nSheets-1),0,0, -1*nSheets);
1617 79 : }
1618 :
1619 10 : void ScTable::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo,
1620 : ScProgress* pProgress )
1621 : {
1622 10 : nTab = nTabNo;
1623 10250 : for ( SCCOL i=0; i <= MAXCOL; i++ )
1624 : {
1625 10240 : aCol[i].UpdateMoveTab( nOldPos, nNewPos, nTabNo );
1626 10240 : if (pProgress)
1627 0 : pProgress->SetState(pProgress->GetState() + aCol[i].GetCodeCount());
1628 : }
1629 :
1630 10 : if (mpRangeName)
1631 0 : mpRangeName->UpdateTabRef(nOldPos, 3, nNewPos);
1632 :
1633 10 : if (IsStreamValid())
1634 0 : SetStreamValid(false);
1635 10 : if (pDBDataNoName)
1636 0 : pDBDataNoName->UpdateMoveTab(nOldPos, nNewPos);
1637 :
1638 10 : if(mpCondFormatList)
1639 10 : mpCondFormatList->UpdateMoveTab(nOldPos, nNewPos);
1640 10 : }
1641 :
1642 95 : void ScTable::UpdateCompile( bool bForceIfNameInUse )
1643 : {
1644 97375 : for (SCCOL i=0; i <= MAXCOL; i++)
1645 : {
1646 97280 : aCol[i].UpdateCompile( bForceIfNameInUse );
1647 : }
1648 95 : }
1649 :
1650 0 : void ScTable::SetTabNo(SCTAB nNewTab)
1651 : {
1652 0 : nTab = nNewTab;
1653 0 : for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].SetTabNo(nNewTab);
1654 0 : }
1655 :
1656 1 : void ScTable::FindRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1657 : std::set<sal_uInt16>& rIndexes) const
1658 : {
1659 4 : for (SCCOL i = nCol1; i <= nCol2 && ValidCol(i); i++)
1660 3 : aCol[i].FindRangeNamesInUse(nRow1, nRow2, rIndexes);
1661 1 : }
1662 :
1663 17 : void ScTable::ExtendPrintArea( OutputDevice* pDev,
1664 : SCCOL /* nStartCol */, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1665 : {
1666 17 : if ( !pColFlags || !pRowFlags )
1667 : {
1668 : OSL_FAIL("keine ColInfo oder RowInfo in ExtendPrintArea");
1669 : return;
1670 : }
1671 :
1672 17 : Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
1673 17 : double nPPTX = aPix1000.X() / 1000.0;
1674 17 : double nPPTY = aPix1000.Y() / 1000.0;
1675 :
1676 : // First, mark those columns that we need to skip i.e. hidden and empty columns.
1677 :
1678 17 : ScFlatBoolColSegments aSkipCols;
1679 17 : aSkipCols.setFalse(0, MAXCOL);
1680 34 : for (SCCOL i = 0; i <= MAXCOL; ++i)
1681 : {
1682 17 : SCCOL nLastCol = i;
1683 17 : if (ColHidden(i, NULL, &nLastCol))
1684 : {
1685 : // Columns are hidden in this range.
1686 0 : aSkipCols.setTrue(i, nLastCol);
1687 : }
1688 : else
1689 : {
1690 : // These columns are visible. Check for empty columns.
1691 17425 : for (SCCOL j = i; j <= nLastCol; ++j)
1692 : {
1693 17408 : if (aCol[j].GetCellCount() == 0)
1694 : // empty
1695 17347 : aSkipCols.setTrue(j,j);
1696 : }
1697 : }
1698 17 : i = nLastCol;
1699 : }
1700 :
1701 : ScFlatBoolColSegments::RangeData aColData;
1702 84 : for (SCCOL nCol = rEndCol; nCol >= 0; --nCol)
1703 : {
1704 67 : if (!aSkipCols.getRangeData(nCol, aColData))
1705 : // Failed to get the data. This should never happen!
1706 : return;
1707 :
1708 67 : if (aColData.mbValue)
1709 : {
1710 : // Skip these columns.
1711 28 : nCol = aColData.mnCol1; // move toward 0.
1712 28 : continue;
1713 : }
1714 :
1715 : // These are visible and non-empty columns.
1716 100 : for (SCCOL nDataCol = nCol; 0 <= nDataCol && nDataCol >= aColData.mnCol1; --nDataCol)
1717 : {
1718 61 : SCCOL nPrintCol = nDataCol;
1719 61 : VisibleDataCellIterator aIter(*mpHiddenRows, aCol[nDataCol]);
1720 61 : ScBaseCell* pCell = aIter.reset(nStartRow);
1721 61 : if (!pCell)
1722 : // No visible cells found in this column. Skip it.
1723 0 : continue;
1724 :
1725 779 : while (pCell)
1726 : {
1727 657 : SCCOL nNewCol = nDataCol;
1728 657 : SCROW nRow = aIter.getRow();
1729 657 : if (nRow > nEndRow)
1730 : // Went past the last row position. Bail out.
1731 : break;
1732 :
1733 657 : MaybeAddExtraColumn(nNewCol, nRow, pDev, nPPTX, nPPTY);
1734 657 : if (nNewCol > nPrintCol)
1735 28 : nPrintCol = nNewCol;
1736 657 : pCell = aIter.next();
1737 : }
1738 :
1739 61 : if (nPrintCol > rEndCol)
1740 : // Make sure we don't shrink the print area.
1741 6 : rEndCol = nPrintCol;
1742 61 : }
1743 39 : nCol = aColData.mnCol1; // move toward 0.
1744 17 : }
1745 : }
1746 :
1747 657 : void ScTable::MaybeAddExtraColumn(SCCOL& rCol, SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY)
1748 : {
1749 657 : ScBaseCell* pCell = aCol[rCol].GetCell(nRow);
1750 657 : if (!pCell || !pCell->HasStringData())
1751 1236 : return;
1752 :
1753 78 : bool bFormula = false; //! ueberge
1754 78 : long nPixel = pCell->GetTextWidth();
1755 :
1756 : // Breite bereits im Idle-Handler berechnet?
1757 78 : if ( TEXTWIDTH_DIRTY == nPixel )
1758 : {
1759 78 : ScNeededSizeOptions aOptions;
1760 78 : aOptions.bTotalSize = true;
1761 78 : aOptions.bFormula = bFormula;
1762 78 : aOptions.bSkipMerged = false;
1763 :
1764 78 : Fraction aZoom(1,1);
1765 78 : nPixel = aCol[rCol].GetNeededSize(
1766 78 : nRow, pDev, nPPTX, nPPTY, aZoom, aZoom, true, aOptions );
1767 78 : pCell->SetTextWidth( (sal_uInt16)nPixel );
1768 : }
1769 :
1770 78 : long nTwips = (long) (nPixel / nPPTX);
1771 78 : long nDocW = GetColWidth( rCol );
1772 :
1773 78 : long nMissing = nTwips - nDocW;
1774 78 : if ( nMissing > 0 )
1775 : {
1776 : // look at alignment
1777 :
1778 28 : const ScPatternAttr* pPattern = GetPattern( rCol, nRow );
1779 28 : const SfxItemSet* pCondSet = pDocument->GetCondResult( rCol, nRow, nTab );
1780 :
1781 : SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
1782 28 : pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue();
1783 28 : if ( eHorJust == SVX_HOR_JUSTIFY_CENTER )
1784 0 : nMissing /= 2; // distributed into both directions
1785 : else
1786 : {
1787 : // STANDARD is LEFT (only text is handled here)
1788 28 : bool bRight = ( eHorJust == SVX_HOR_JUSTIFY_RIGHT );
1789 28 : if ( IsLayoutRTL() )
1790 0 : bRight = !bRight;
1791 28 : if ( bRight )
1792 0 : nMissing = 0; // extended only to the left (logical)
1793 : }
1794 : }
1795 :
1796 78 : SCCOL nNewCol = rCol;
1797 350 : while (nMissing > 0 && nNewCol < MAXCOL)
1798 : {
1799 194 : ScBaseCell* pNextCell = aCol[nNewCol+1].GetCell(nRow);
1800 194 : if (pNextCell && pNextCell->GetCellType() != CELLTYPE_NOTE)
1801 : // Cell content in a next column ends display of this string.
1802 0 : nMissing = 0;
1803 : else
1804 194 : nMissing -= GetColWidth(++nNewCol);
1805 : }
1806 78 : rCol = nNewCol;
1807 : }
1808 :
1809 : namespace {
1810 :
1811 : class SetTableIndex : public ::std::unary_function<ScRange, void>
1812 : {
1813 : SCTAB mnTab;
1814 : public:
1815 3 : SetTableIndex(SCTAB nTab) : mnTab(nTab) {}
1816 :
1817 0 : void operator() (ScRange& rRange) const
1818 : {
1819 0 : rRange.aStart.SetTab(mnTab);
1820 0 : rRange.aEnd.SetTab(mnTab);
1821 0 : }
1822 : };
1823 :
1824 0 : void setPrintRange(ScRange*& pRange1, const ScRange* pRange2)
1825 : {
1826 0 : if (pRange2)
1827 : {
1828 0 : if (pRange1)
1829 0 : *pRange1 = *pRange2;
1830 : else
1831 0 : pRange1 = new ScRange(*pRange2);
1832 : }
1833 : else
1834 0 : DELETEZ(pRange1);
1835 0 : }
1836 :
1837 : }
1838 :
1839 3 : void ScTable::CopyPrintRange(const ScTable& rTable)
1840 : {
1841 : // The table index shouldn't be used when the print range is used, but
1842 : // just in case set the correct table index.
1843 :
1844 3 : aPrintRanges = rTable.aPrintRanges;
1845 3 : ::std::for_each(aPrintRanges.begin(), aPrintRanges.end(), SetTableIndex(nTab));
1846 :
1847 3 : bPrintEntireSheet = rTable.bPrintEntireSheet;
1848 :
1849 3 : delete pRepeatColRange;
1850 3 : pRepeatColRange = NULL;
1851 3 : if (rTable.pRepeatColRange)
1852 : {
1853 0 : pRepeatColRange = new ScRange(*rTable.pRepeatColRange);
1854 0 : pRepeatColRange->aStart.SetTab(nTab);
1855 0 : pRepeatColRange->aEnd.SetTab(nTab);
1856 : }
1857 :
1858 3 : delete pRepeatRowRange;
1859 3 : pRepeatRowRange = NULL;
1860 3 : if (rTable.pRepeatRowRange)
1861 : {
1862 0 : pRepeatRowRange = new ScRange(*rTable.pRepeatRowRange);
1863 0 : pRepeatRowRange->aStart.SetTab(nTab);
1864 0 : pRepeatRowRange->aEnd.SetTab(nTab);
1865 : }
1866 3 : }
1867 :
1868 30 : void ScTable::DoColResize( SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd )
1869 : {
1870 124 : for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
1871 94 : aCol[nCol].Resize(aCol[nCol].GetCellCount() + nAdd);
1872 30 : }
1873 :
1874 0 : void ScTable::SetRepeatColRange( const ScRange* pNew )
1875 : {
1876 0 : setPrintRange( pRepeatColRange, pNew );
1877 :
1878 0 : if (IsStreamValid())
1879 0 : SetStreamValid(false);
1880 :
1881 0 : InvalidatePageBreaks();
1882 0 : }
1883 :
1884 0 : void ScTable::SetRepeatRowRange( const ScRange* pNew )
1885 : {
1886 0 : setPrintRange( pRepeatRowRange, pNew );
1887 :
1888 0 : if (IsStreamValid())
1889 0 : SetStreamValid(false);
1890 :
1891 0 : InvalidatePageBreaks();
1892 0 : }
1893 :
1894 6 : void ScTable::ClearPrintRanges()
1895 : {
1896 6 : aPrintRanges.clear();
1897 6 : bPrintEntireSheet = false;
1898 :
1899 6 : if (IsStreamValid())
1900 0 : SetStreamValid(false);
1901 :
1902 6 : InvalidatePageBreaks(); // #i117952# forget page breaks for an old print range
1903 6 : }
1904 :
1905 0 : void ScTable::AddPrintRange( const ScRange& rNew )
1906 : {
1907 0 : bPrintEntireSheet = false;
1908 0 : if( aPrintRanges.size() < 0xFFFF )
1909 0 : aPrintRanges.push_back( rNew );
1910 :
1911 0 : if (IsStreamValid())
1912 0 : SetStreamValid(false);
1913 :
1914 0 : InvalidatePageBreaks();
1915 0 : }
1916 :
1917 :
1918 0 : void ScTable::SetPrintEntireSheet()
1919 : {
1920 0 : if( !IsPrintEntireSheet() )
1921 : {
1922 0 : ClearPrintRanges();
1923 0 : bPrintEntireSheet = true;
1924 : }
1925 0 : }
1926 :
1927 69 : const ScRange* ScTable::GetPrintRange(sal_uInt16 nPos) const
1928 : {
1929 69 : return (nPos < GetPrintRangeCount()) ? &aPrintRanges[ nPos ] : NULL;
1930 : }
1931 :
1932 10 : void ScTable::FillPrintSaver( ScPrintSaverTab& rSaveTab ) const
1933 : {
1934 10 : rSaveTab.SetAreas( aPrintRanges, bPrintEntireSheet );
1935 10 : rSaveTab.SetRepeat( pRepeatColRange, pRepeatRowRange );
1936 10 : }
1937 :
1938 0 : void ScTable::RestorePrintRanges( const ScPrintSaverTab& rSaveTab )
1939 : {
1940 0 : aPrintRanges = rSaveTab.GetPrintRanges();
1941 0 : bPrintEntireSheet = rSaveTab.IsEntireSheet();
1942 0 : SetRepeatColRange( rSaveTab.GetRepeatCol() );
1943 0 : SetRepeatRowRange( rSaveTab.GetRepeatRow() );
1944 :
1945 0 : InvalidatePageBreaks(); // #i117952# forget page breaks for an old print range
1946 0 : UpdatePageBreaks(NULL);
1947 0 : }
1948 :
1949 : SCROW ScTable::VisibleDataCellIterator::ROW_NOT_FOUND = -1;
1950 :
1951 61 : ScTable::VisibleDataCellIterator::VisibleDataCellIterator(ScFlatBoolRowSegments& rRowSegs, ScColumn& rColumn) :
1952 : mrRowSegs(rRowSegs),
1953 : mrColumn(rColumn),
1954 : mpCell(NULL),
1955 : mnCurRow(ROW_NOT_FOUND),
1956 61 : mnUBound(ROW_NOT_FOUND)
1957 : {
1958 61 : }
1959 :
1960 61 : ScTable::VisibleDataCellIterator::~VisibleDataCellIterator()
1961 : {
1962 61 : }
1963 :
1964 61 : ScBaseCell* ScTable::VisibleDataCellIterator::reset(SCROW nRow)
1965 : {
1966 61 : if (nRow > MAXROW)
1967 : {
1968 0 : mnCurRow = ROW_NOT_FOUND;
1969 0 : return NULL;
1970 : }
1971 :
1972 : ScFlatBoolRowSegments::RangeData aData;
1973 61 : if (!mrRowSegs.getRangeData(nRow, aData))
1974 : {
1975 0 : mnCurRow = ROW_NOT_FOUND;
1976 0 : return NULL;
1977 : }
1978 :
1979 61 : if (!aData.mbValue)
1980 : {
1981 : // specified row is visible. Take it.
1982 61 : mnCurRow = nRow;
1983 61 : mnUBound = aData.mnRow2;
1984 : }
1985 : else
1986 : {
1987 : // specified row is not-visible. The first visible row is the start of
1988 : // the next segment.
1989 0 : mnCurRow = aData.mnRow2 + 1;
1990 0 : mnUBound = mnCurRow; // get range data on the next iteration.
1991 0 : if (mnCurRow > MAXROW)
1992 : {
1993 : // Make sure the row doesn't exceed our current limit.
1994 0 : mnCurRow = ROW_NOT_FOUND;
1995 0 : return NULL;
1996 : }
1997 : }
1998 :
1999 61 : mpCell = mrColumn.GetCell(mnCurRow);
2000 61 : if (mpCell)
2001 : // First visible cell found.
2002 54 : return mpCell;
2003 :
2004 : // Find a first visible cell below this row (if any).
2005 7 : return next();
2006 : }
2007 :
2008 664 : ScBaseCell* ScTable::VisibleDataCellIterator::next()
2009 : {
2010 664 : if (mnCurRow == ROW_NOT_FOUND)
2011 0 : return NULL;
2012 :
2013 1328 : while (mrColumn.GetNextDataPos(mnCurRow))
2014 : {
2015 603 : if (mnCurRow > mnUBound)
2016 : {
2017 : // We don't know the visibility of this row range. Query it.
2018 : ScFlatBoolRowSegments::RangeData aData;
2019 0 : if (!mrRowSegs.getRangeData(mnCurRow, aData))
2020 : {
2021 0 : mnCurRow = ROW_NOT_FOUND;
2022 0 : return NULL;
2023 : }
2024 :
2025 0 : if (aData.mbValue)
2026 : {
2027 : // This row is invisible. Skip to the last invisible row and
2028 : // try again.
2029 0 : mnCurRow = mnUBound = aData.mnRow2;
2030 0 : continue;
2031 : }
2032 :
2033 : // This row is visible.
2034 0 : mnUBound = aData.mnRow2;
2035 : }
2036 :
2037 603 : mpCell = mrColumn.GetCell(mnCurRow);
2038 603 : if (mpCell)
2039 603 : return mpCell;
2040 : }
2041 61 : mnCurRow = ROW_NOT_FOUND;
2042 61 : return NULL;
2043 : }
2044 :
2045 657 : SCROW ScTable::VisibleDataCellIterator::getRow() const
2046 : {
2047 657 : return mnCurRow;
2048 : }
2049 :
2050 10 : void ScTable::SetAnonymousDBData(ScDBData* pDBData)
2051 : {
2052 10 : delete pDBDataNoName;
2053 10 : pDBDataNoName = pDBData;
2054 10 : }
2055 :
2056 102 : ScDBData* ScTable::GetAnonymousDBData()
2057 : {
2058 102 : return pDBDataNoName;
2059 : }
2060 :
2061 34 : sal_uLong ScTable::AddCondFormat( ScConditionalFormat* pNew )
2062 : {
2063 34 : if(!mpCondFormatList)
2064 0 : mpCondFormatList.reset(new ScConditionalFormatList());
2065 :
2066 34 : sal_uLong nMax = 0;
2067 390 : for(ScConditionalFormatList::const_iterator itr = mpCondFormatList->begin();
2068 260 : itr != mpCondFormatList->end(); ++itr)
2069 : {
2070 96 : sal_uLong nKey = itr->GetKey();
2071 96 : if(nKey > nMax)
2072 96 : nMax = nKey;
2073 : }
2074 :
2075 34 : pNew->SetKey(nMax+1);
2076 34 : mpCondFormatList->InsertNew(pNew);
2077 :
2078 34 : return nMax + 1;
2079 : }
2080 :
2081 0 : void ScTable::DeleteConditionalFormat( sal_uLong nIndex )
2082 : {
2083 0 : mpCondFormatList->erase(nIndex);
2084 0 : }
2085 :
2086 3 : void ScTable::SetCondFormList( ScConditionalFormatList* pNew )
2087 : {
2088 3 : mpCondFormatList.reset( pNew );
2089 3 : }
2090 :
2091 8613 : ScConditionalFormatList* ScTable::GetCondFormList()
2092 : {
2093 8613 : if(!mpCondFormatList)
2094 0 : mpCondFormatList.reset( new ScConditionalFormatList() );
2095 :
2096 8613 : return mpCondFormatList.get();
2097 : }
2098 :
2099 0 : const ScConditionalFormatList* ScTable::GetCondFormList() const
2100 : {
2101 0 : return mpCondFormatList.get();
2102 : }
2103 :
2104 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|