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