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