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