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 "table.hxx"
21 : #include "patattr.hxx"
22 : #include "docpool.hxx"
23 : #include "formulacell.hxx"
24 : #include "document.hxx"
25 : #include "drwlayer.hxx"
26 : #include "olinetab.hxx"
27 : #include "rechead.hxx"
28 : #include "stlpool.hxx"
29 : #include "attarray.hxx"
30 : #include "markdata.hxx"
31 : #include "progress.hxx"
32 : #include "dociter.hxx"
33 : #include "conditio.hxx"
34 : #include "chartlis.hxx"
35 : #include "fillinfo.hxx"
36 : #include "bcaslot.hxx"
37 : #include "postit.hxx"
38 : #include "sheetevents.hxx"
39 : #include "globstr.hrc"
40 : #include "segmenttree.hxx"
41 : #include "queryparam.hxx"
42 : #include "queryentry.hxx"
43 : #include "dbdata.hxx"
44 : #include "colorscale.hxx"
45 : #include "tokenarray.hxx"
46 : #include "clipcontext.hxx"
47 : #include "types.hxx"
48 : #include "editutil.hxx"
49 : #include "mtvcellfunc.hxx"
50 : #include "refupdatecontext.hxx"
51 : #include "scopetools.hxx"
52 : #include "tabprotection.hxx"
53 : #include <rowheightcontext.hxx>
54 : #include <refhint.hxx>
55 :
56 : #include "scitems.hxx"
57 : #include <editeng/boxitem.hxx>
58 : #include "editeng/editobj.hxx"
59 : #include <svl/poolcach.hxx>
60 : #include <unotools/charclass.hxx>
61 : #include <math.h>
62 : #include <svl/PasswordHelper.hxx>
63 : #include <unotools/transliterationwrapper.hxx>
64 :
65 : namespace {
66 :
67 : class ColumnRegroupFormulaCells
68 : {
69 : ScColumn* mpCols;
70 : public:
71 0 : ColumnRegroupFormulaCells(ScColumn* pCols) : mpCols(pCols) {}
72 :
73 0 : void operator() (SCCOL nCol)
74 : {
75 0 : mpCols[nCol].RegroupFormulaCells();
76 0 : }
77 : };
78 :
79 : }
80 :
81 0 : sal_uInt16 ScTable::GetTextWidth(SCCOL nCol, SCROW nRow) const
82 : {
83 0 : return aCol[nCol].GetTextWidth(nRow);
84 : }
85 :
86 0 : bool ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline )
87 : {
88 0 : sal_uInt16 nOldSizeX = 0;
89 0 : sal_uInt16 nOldSizeY = 0;
90 0 : sal_uInt16 nNewSizeX = 0;
91 0 : sal_uInt16 nNewSizeY = 0;
92 :
93 0 : if (pOutlineTable)
94 : {
95 0 : nOldSizeX = pOutlineTable->GetColArray()->GetDepth();
96 0 : nOldSizeY = pOutlineTable->GetRowArray()->GetDepth();
97 0 : delete pOutlineTable;
98 : }
99 :
100 0 : if (pNewOutline)
101 : {
102 0 : pOutlineTable = new ScOutlineTable( *pNewOutline );
103 0 : nNewSizeX = pOutlineTable->GetColArray()->GetDepth();
104 0 : nNewSizeY = pOutlineTable->GetRowArray()->GetDepth();
105 : }
106 : else
107 0 : pOutlineTable = NULL;
108 :
109 0 : return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY ); // Groesse geaendert ?
110 : }
111 :
112 :
113 0 : void ScTable::StartOutlineTable()
114 : {
115 0 : if (!pOutlineTable)
116 0 : pOutlineTable = new ScOutlineTable;
117 0 : }
118 :
119 :
120 0 : void ScTable::SetSheetEvents( const ScSheetEvents* pNew )
121 : {
122 0 : delete pSheetEvents;
123 0 : if (pNew)
124 0 : pSheetEvents = new ScSheetEvents(*pNew);
125 : else
126 0 : pSheetEvents = NULL;
127 :
128 0 : SetCalcNotification( false ); // discard notifications before the events were set
129 :
130 0 : if (IsStreamValid())
131 0 : SetStreamValid(false);
132 0 : }
133 :
134 :
135 0 : void ScTable::SetCalcNotification( bool bSet )
136 : {
137 0 : bCalcNotification = bSet;
138 0 : }
139 :
140 :
141 0 : bool ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize ) const
142 : {
143 0 : bool bTest = true;
144 :
145 0 : if ( nStartCol==0 && nEndCol==MAXCOL && pOutlineTable )
146 0 : bTest = pOutlineTable->TestInsertRow(nSize);
147 :
148 0 : for (SCCOL i=nStartCol; (i<=nEndCol) && bTest; i++)
149 0 : bTest = aCol[i].TestInsertRow(nStartRow, nSize);
150 :
151 0 : return bTest;
152 : }
153 :
154 :
155 0 : void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize )
156 : {
157 0 : if (nStartCol==0 && nEndCol==MAXCOL)
158 : {
159 0 : if (mpRowHeights && pRowFlags)
160 : {
161 0 : mpRowHeights->insertSegment(nStartRow, nSize, false);
162 0 : sal_uInt8 nNewFlags = pRowFlags->Insert( nStartRow, nSize);
163 : // only copy manual size flag, clear all others
164 0 : if (nNewFlags && (nNewFlags != CR_MANUALSIZE))
165 0 : pRowFlags->SetValue( nStartRow, nStartRow + nSize - 1,
166 0 : nNewFlags & CR_MANUALSIZE);
167 : }
168 :
169 0 : if (pOutlineTable)
170 0 : pOutlineTable->InsertRow( nStartRow, nSize );
171 :
172 0 : mpFilteredRows->insertSegment(nStartRow, nSize, true);
173 0 : mpHiddenRows->insertSegment(nStartRow, nSize, true);
174 :
175 0 : if (!maRowManualBreaks.empty())
176 : {
177 : // Copy all breaks up to nStartRow (non-inclusive).
178 0 : ::std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
179 0 : ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
180 :
181 : // Copy all breaks from nStartRow (inclusive) to the last element,
182 : // but add nSize to each value.
183 0 : ::std::set<SCROW>::iterator itr2 = maRowManualBreaks.end();
184 0 : for (; itr1 != itr2; ++itr1)
185 0 : aNewBreaks.insert(static_cast<SCROW>(*itr1 + nSize));
186 :
187 0 : maRowManualBreaks.swap(aNewBreaks);
188 : }
189 : }
190 :
191 0 : for (SCCOL j=nStartCol; j<=nEndCol; j++)
192 0 : aCol[j].InsertRow( nStartRow, nSize );
193 :
194 0 : mpCondFormatList->InsertRow(nTab, nStartCol, nEndCol, nStartRow, nSize);
195 :
196 0 : InvalidatePageBreaks();
197 :
198 0 : if (IsStreamValid())
199 : // TODO: In the future we may want to check if the table has been
200 : // really modified before setting the stream invalid.
201 0 : SetStreamValid(false);
202 0 : }
203 :
204 :
205 0 : void ScTable::DeleteRow(
206 : const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize,
207 : bool* pUndoOutline )
208 : {
209 0 : if (nStartCol==0 && nEndCol==MAXCOL)
210 : {
211 0 : if (pRowFlags)
212 0 : pRowFlags->Remove( nStartRow, nSize);
213 :
214 0 : if (mpRowHeights)
215 0 : mpRowHeights->removeSegment(nStartRow, nStartRow+nSize);
216 :
217 0 : if (pOutlineTable)
218 0 : if (pOutlineTable->DeleteRow( nStartRow, nSize ))
219 0 : if (pUndoOutline)
220 0 : *pUndoOutline = true;
221 :
222 0 : mpFilteredRows->removeSegment(nStartRow, nStartRow+nSize);
223 0 : mpHiddenRows->removeSegment(nStartRow, nStartRow+nSize);
224 :
225 0 : if (!maRowManualBreaks.empty())
226 : {
227 : // Erase all manual breaks between nStartRow and nStartRow + nSize - 1 (inclusive).
228 0 : std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow);
229 0 : std::set<SCROW>::iterator itr2 = maRowManualBreaks.upper_bound(static_cast<SCROW>(nStartRow + nSize - 1));
230 0 : maRowManualBreaks.erase(itr1, itr2);
231 :
232 : // Copy all breaks from the 1st element up to nStartRow to the new container.
233 0 : itr1 = maRowManualBreaks.lower_bound(nStartRow);
234 0 : ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1);
235 :
236 : // Copy all breaks from nStartRow to the last element, but subtract each value by nSize.
237 0 : itr2 = maRowManualBreaks.end();
238 0 : for (; itr1 != itr2; ++itr1)
239 0 : aNewBreaks.insert(static_cast<SCROW>(*itr1 - nSize));
240 :
241 0 : maRowManualBreaks.swap(aNewBreaks);
242 : }
243 : }
244 :
245 : { // scope for bulk broadcast
246 0 : ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
247 0 : for (SCCOL j=nStartCol; j<=nEndCol; j++)
248 0 : aCol[j].DeleteRow( nStartRow, nSize );
249 : }
250 :
251 0 : std::vector<SCCOL> aRegroupCols;
252 0 : rRegroupCols.getColumns(nTab, aRegroupCols);
253 0 : std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
254 :
255 0 : InvalidatePageBreaks();
256 :
257 0 : if (IsStreamValid())
258 : // TODO: In the future we may want to check if the table has been
259 : // really modified before setting the stream invalid.
260 0 : SetStreamValid(false);
261 0 : }
262 :
263 :
264 0 : bool ScTable::TestInsertCol( SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) const
265 : {
266 0 : bool bTest = true;
267 :
268 0 : if ( nStartRow==0 && nEndRow==MAXROW && pOutlineTable )
269 0 : bTest = pOutlineTable->TestInsertCol(nSize);
270 :
271 0 : if ( nSize > static_cast<SCSIZE>(MAXCOL) )
272 0 : bTest = false;
273 :
274 0 : for (SCCOL i=MAXCOL; (i+static_cast<SCCOL>(nSize)>MAXCOL) && bTest; i--)
275 0 : bTest = aCol[i].TestInsertCol(nStartRow, nEndRow);
276 :
277 0 : return bTest;
278 : }
279 :
280 :
281 0 : void ScTable::InsertCol(
282 : const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize )
283 : {
284 0 : if (nStartRow==0 && nEndRow==MAXROW)
285 : {
286 0 : if (pColWidth && pColFlags)
287 : {
288 0 : memmove( &pColWidth[nStartCol+nSize], &pColWidth[nStartCol],
289 0 : (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
290 0 : memmove( &pColFlags[nStartCol+nSize], &pColFlags[nStartCol],
291 0 : (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
292 : }
293 0 : if (pOutlineTable)
294 0 : pOutlineTable->InsertCol( nStartCol, nSize );
295 :
296 0 : mpHiddenCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true);
297 0 : mpFilteredCols->insertSegment(nStartCol, static_cast<SCCOL>(nSize), true);
298 :
299 0 : if (!maColManualBreaks.empty())
300 : {
301 0 : std::set<SCCOL>::reverse_iterator rit = maColManualBreaks.rbegin();
302 0 : while (rit != maColManualBreaks.rend())
303 : {
304 0 : SCCOL nCol = *rit;
305 0 : if (nCol < nStartCol)
306 0 : break; // while
307 : else
308 : {
309 0 : maColManualBreaks.erase( (++rit).base());
310 0 : maColManualBreaks.insert( static_cast<SCCOL>( nCol + nSize));
311 : }
312 : }
313 : }
314 : }
315 :
316 :
317 0 : if ((nStartRow == 0) && (nEndRow == MAXROW))
318 : {
319 0 : for (SCSIZE i=0; i < nSize; i++)
320 0 : for (SCCOL nCol = MAXCOL; nCol > nStartCol; nCol--)
321 0 : aCol[nCol].SwapCol(aCol[nCol-1]);
322 : }
323 : else
324 : {
325 0 : for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++)
326 0 : aCol[MAXCOL - nSize - i].MoveTo(nStartRow, nEndRow, aCol[MAXCOL - i]);
327 : }
328 :
329 0 : std::vector<SCCOL> aRegroupCols;
330 0 : rRegroupCols.getColumns(nTab, aRegroupCols);
331 0 : std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
332 :
333 0 : if (nStartCol>0) // copy old attributes
334 : {
335 : sal_uInt16 nWhichArray[2];
336 0 : nWhichArray[0] = ATTR_MERGE;
337 0 : nWhichArray[1] = 0;
338 :
339 0 : sc::CopyToDocContext aCxt(*pDocument);
340 0 : for (SCSIZE i=0; i<nSize; i++)
341 : {
342 0 : aCol[nStartCol-1].CopyToColumn(aCxt, nStartRow, nEndRow, IDF_ATTRIB,
343 0 : false, aCol[nStartCol+i] );
344 0 : aCol[nStartCol+i].RemoveFlags( nStartRow, nEndRow,
345 0 : SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
346 0 : aCol[nStartCol+i].ClearItems( nStartRow, nEndRow, nWhichArray );
347 0 : }
348 : }
349 :
350 0 : mpCondFormatList->InsertCol(nTab, nStartRow, nEndRow, nStartCol, nSize);
351 :
352 0 : InvalidatePageBreaks();
353 :
354 0 : if (IsStreamValid())
355 : // TODO: In the future we may want to check if the table has been
356 : // really modified before setting the stream invalid.
357 0 : SetStreamValid(false);
358 0 : }
359 :
360 0 : void ScTable::DeleteCol(
361 : const sc::ColumnSet& rRegroupCols, SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize, bool* pUndoOutline )
362 : {
363 0 : if (nStartRow==0 && nEndRow==MAXROW)
364 : {
365 0 : if (pColWidth && pColFlags)
366 : {
367 0 : memmove( &pColWidth[nStartCol], &pColWidth[nStartCol+nSize],
368 0 : (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColWidth[0]) );
369 0 : memmove( &pColFlags[nStartCol], &pColFlags[nStartCol+nSize],
370 0 : (MAXCOL - nStartCol + 1 - nSize) * sizeof(pColFlags[0]) );
371 : }
372 0 : if (pOutlineTable)
373 0 : if (pOutlineTable->DeleteCol( nStartCol, nSize ))
374 0 : if (pUndoOutline)
375 0 : *pUndoOutline = true;
376 :
377 0 : SCCOL nRmSize = nStartCol + static_cast<SCCOL>(nSize);
378 0 : mpHiddenCols->removeSegment(nStartCol, nRmSize);
379 0 : mpFilteredCols->removeSegment(nStartCol, nRmSize);
380 :
381 0 : if (!maColManualBreaks.empty())
382 : {
383 0 : std::set<SCCOL>::iterator it = maColManualBreaks.upper_bound( static_cast<SCCOL>( nStartCol + nSize - 1));
384 0 : maColManualBreaks.erase( maColManualBreaks.lower_bound( nStartCol), it);
385 0 : while (it != maColManualBreaks.end())
386 : {
387 0 : SCCOL nCol = *it;
388 0 : maColManualBreaks.erase( it++);
389 0 : maColManualBreaks.insert( static_cast<SCCOL>( nCol - nSize));
390 : }
391 : }
392 : }
393 :
394 : { // scope for bulk broadcast
395 0 : ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
396 0 : for (SCSIZE i = 0; i < nSize; i++)
397 0 : aCol[nStartCol + i].DeleteArea(nStartRow, nEndRow, IDF_ALL);
398 : }
399 :
400 0 : if ((nStartRow == 0) && (nEndRow == MAXROW))
401 : {
402 0 : for (SCSIZE i=0; i < nSize; i++)
403 0 : for (SCCOL nCol = nStartCol; nCol < MAXCOL; nCol++)
404 0 : aCol[nCol].SwapCol(aCol[nCol+1]);
405 : }
406 : else
407 : {
408 0 : for (SCSIZE i=0; static_cast<SCCOL>(i+nSize)+nStartCol <= MAXCOL; i++)
409 0 : aCol[nStartCol + nSize + i].MoveTo(nStartRow, nEndRow, aCol[nStartCol + i]);
410 : }
411 :
412 0 : std::vector<SCCOL> aRegroupCols;
413 0 : rRegroupCols.getColumns(nTab, aRegroupCols);
414 0 : std::for_each(aRegroupCols.begin(), aRegroupCols.end(), ColumnRegroupFormulaCells(aCol));
415 :
416 0 : InvalidatePageBreaks();
417 :
418 0 : if (IsStreamValid())
419 : // TODO: In the future we may want to check if the table has been
420 : // really modified before setting the stream invalid.
421 0 : SetStreamValid(false);
422 0 : }
423 :
424 :
425 0 : void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nDelFlag)
426 : {
427 0 : if (nCol2 > MAXCOL) nCol2 = MAXCOL;
428 0 : if (nRow2 > MAXROW) nRow2 = MAXROW;
429 0 : if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
430 : {
431 : { // scope for bulk broadcast
432 0 : ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
433 0 : for (SCCOL i = nCol1; i <= nCol2; i++)
434 0 : aCol[i].DeleteArea(nRow1, nRow2, nDelFlag);
435 : }
436 :
437 :
438 : // Zellschutz auf geschuetzter Tabelle nicht setzen
439 :
440 :
441 0 : if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
442 : {
443 0 : ScPatternAttr aPattern(pDocument->GetPool());
444 0 : aPattern.GetItemSet().Put( ScProtectionAttr( false ) );
445 0 : ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
446 : }
447 :
448 0 : if( nDelFlag & IDF_ATTRIB )
449 0 : mpCondFormatList->DeleteArea( nCol1, nRow1, nCol2, nRow2 );
450 : }
451 :
452 0 : if (IsStreamValid())
453 : // TODO: In the future we may want to check if the table has been
454 : // really modified before setting the stream invalid.
455 0 : SetStreamValid(false);
456 0 : }
457 :
458 :
459 0 : void ScTable::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark, bool bBroadcast )
460 : {
461 : { // scope for bulk broadcast
462 0 : ScBulkBroadcast aBulkBroadcast( pDocument->GetBASM());
463 0 : for (SCCOL i=0; i<=MAXCOL; i++)
464 0 : aCol[i].DeleteSelection(nDelFlag, rMark, bBroadcast);
465 : }
466 :
467 0 : ScRangeList aRangeList;
468 0 : rMark.FillRangeListWithMarks(&aRangeList, false);
469 :
470 0 : for (size_t i = 0; i < aRangeList.size(); ++i)
471 : {
472 0 : ScRange* pRange = aRangeList[i];
473 :
474 0 : if((nDelFlag & IDF_ATTRIB) && pRange && pRange->aStart.Tab() == nTab)
475 0 : mpCondFormatList->DeleteArea( pRange->aStart.Col(), pRange->aStart.Row(), pRange->aEnd.Col(), pRange->aEnd.Row() );
476 : }
477 :
478 :
479 : // Zellschutz auf geschuetzter Tabelle nicht setzen
480 :
481 :
482 0 : if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
483 : {
484 0 : ScDocumentPool* pPool = pDocument->GetPool();
485 0 : SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END );
486 0 : aSet.Put( ScProtectionAttr( false ) );
487 0 : SfxItemPoolCache aCache( pPool, &aSet );
488 0 : ApplySelectionCache( &aCache, rMark );
489 : }
490 :
491 0 : if (IsStreamValid())
492 : // TODO: In the future we may want to check if the table has been
493 : // really modified before setting the stream invalid.
494 0 : SetStreamValid(false);
495 0 : }
496 :
497 :
498 : // pTable = Clipboard
499 0 : void ScTable::CopyToClip(
500 : sc::CopyToClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
501 : ScTable* pTable )
502 : {
503 0 : if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
504 : {
505 : // copy content
506 : //local range names need to be copied first for formula cells
507 0 : if (!pTable->mpRangeName && mpRangeName)
508 0 : pTable->mpRangeName = new ScRangeName(*mpRangeName);
509 :
510 : SCCOL i;
511 :
512 0 : for ( i = nCol1; i <= nCol2; i++)
513 0 : aCol[i].CopyToClip(rCxt, nRow1, nRow2, pTable->aCol[i]); // notes are handled at column level
514 :
515 : // copy widths/heights, and only "hidden", "filtered" and "manual" flags
516 : // also for all preceding columns/rows, to have valid positions for drawing objects
517 :
518 0 : if (pColWidth && pTable->pColWidth)
519 0 : for (i=0; i<=nCol2; i++)
520 0 : pTable->pColWidth[i] = pColWidth[i];
521 :
522 0 : pTable->CopyColHidden(*this, 0, nCol2);
523 0 : pTable->CopyColFiltered(*this, 0, nCol2);
524 0 : if (pDBDataNoName)
525 0 : pTable->SetAnonymousDBData(new ScDBData(*pDBDataNoName));
526 :
527 :
528 0 : if (pRowFlags && pTable->pRowFlags && mpRowHeights && pTable->mpRowHeights)
529 : {
530 0 : pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, CR_MANUALSIZE);
531 0 : pTable->CopyRowHeight(*this, 0, nRow2, 0);
532 : }
533 :
534 0 : pTable->CopyRowHidden(*this, 0, nRow2);
535 0 : pTable->CopyRowFiltered(*this, 0, nRow2);
536 :
537 : // ggf. Formeln durch Werte ersetzen
538 :
539 0 : if ( IsProtected() )
540 0 : for (i = nCol1; i <= nCol2; i++)
541 0 : pTable->aCol[i].RemoveProtected(nRow1, nRow2);
542 :
543 0 : pTable->mpCondFormatList.reset(new ScConditionalFormatList(pTable->pDocument, *mpCondFormatList));
544 : }
545 0 : }
546 :
547 0 : void ScTable::CopyToClip(
548 : sc::CopyToClipContext& rCxt, const ScRangeList& rRanges, ScTable* pTable )
549 : {
550 0 : ScRangeList aRanges(rRanges);
551 0 : for ( size_t i = 0, nListSize = aRanges.size(); i < nListSize; ++i )
552 : {
553 0 : ScRange* p = aRanges[ i ];
554 : CopyToClip(
555 0 : rCxt, p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), pTable);
556 0 : }
557 0 : }
558 :
559 0 : void ScTable::CopyStaticToDocument(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScTable* pDestTab)
560 : {
561 0 : if (nCol1 > nCol2)
562 0 : return;
563 :
564 0 : for (SCCOL i = nCol1; i <= nCol2; ++i)
565 : {
566 0 : ScColumn& rSrcCol = aCol[i];
567 0 : ScColumn& rDestCol = pDestTab->aCol[i];
568 0 : rSrcCol.CopyStaticToDocument(nRow1, nRow2, rDestCol);
569 : }
570 : }
571 :
572 0 : void ScTable::CopyCellToDocument(SCCOL nSrcCol, SCROW nSrcRow, SCCOL nDestCol, SCROW nDestRow, ScTable& rDestTab )
573 : {
574 0 : if (!ValidColRow(nSrcCol, nSrcRow) || !ValidColRow(nDestCol, nDestRow))
575 0 : return;
576 :
577 0 : ScColumn& rSrcCol = aCol[nSrcCol];
578 0 : ScColumn& rDestCol = rDestTab.aCol[nDestCol];
579 0 : rSrcCol.CopyCellToDocument(nSrcRow, nDestRow, rDestCol);
580 : }
581 :
582 0 : void ScTable::CopyConditionalFormat( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
583 : SCsCOL nDx, SCsROW nDy, ScTable* pTable)
584 : {
585 0 : ScRange aOldRange( nCol1 - nDx, nRow1 - nDy, pTable->nTab, nCol2 - nDx, nRow2 - nDy, pTable->nTab);
586 0 : ScRange aNewRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
587 0 : bool bSameDoc = pDocument == pTable->pDocument;
588 :
589 0 : for(ScConditionalFormatList::const_iterator itr = pTable->mpCondFormatList->begin(),
590 0 : itrEnd = pTable->mpCondFormatList->end(); itr != itrEnd; ++itr)
591 : {
592 0 : const ScRangeList& rCondFormatRange = itr->GetRange();
593 0 : if(!rCondFormatRange.Intersects( aOldRange ))
594 0 : continue;
595 :
596 0 : ScRangeList aIntersectedRange = rCondFormatRange.GetIntersectedRange(aOldRange);
597 0 : ScConditionalFormat* pNewFormat = itr->Clone(pDocument);
598 :
599 0 : pNewFormat->AddRange(aIntersectedRange);
600 0 : sc::RefUpdateContext aRefCxt(*pDocument);
601 0 : aRefCxt.meMode = URM_COPY;
602 0 : aRefCxt.maRange = aNewRange;
603 0 : aRefCxt.mnColDelta = nDx;
604 0 : aRefCxt.mnRowDelta = nDy;
605 0 : aRefCxt.mnTabDelta = nTab - pTable->nTab;
606 0 : pNewFormat->UpdateReference(aRefCxt, true);
607 :
608 0 : sal_uLong nMax = 0;
609 0 : for(ScConditionalFormatList::const_iterator itrCond = mpCondFormatList->begin();
610 0 : itrCond != mpCondFormatList->end(); ++itrCond)
611 : {
612 0 : if(itrCond->GetKey() > nMax)
613 0 : nMax = itrCond->GetKey();
614 : }
615 0 : pNewFormat->SetKey(nMax + 1);
616 0 : mpCondFormatList->InsertNew(pNewFormat);
617 :
618 0 : if(!bSameDoc)
619 : {
620 0 : for(size_t i = 0, n = pNewFormat->size();
621 : i < n; ++i)
622 : {
623 0 : OUString aStyleName;
624 0 : const ScFormatEntry* pEntry = pNewFormat->GetEntry(i);
625 0 : if(pEntry->GetType() == condformat::CONDITION)
626 0 : aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle();
627 0 : else if(pEntry->GetType() == condformat::DATE)
628 0 : aStyleName = static_cast<const ScCondDateFormatEntry*>(pEntry)->GetStyleName();
629 :
630 0 : if(!aStyleName.isEmpty())
631 : {
632 0 : if(pDocument->GetStyleSheetPool()->Find(aStyleName, SFX_STYLE_FAMILY_PARA))
633 0 : continue;
634 :
635 : pDocument->GetStyleSheetPool()->CopyStyleFrom(
636 0 : pTable->pDocument->GetStyleSheetPool(), aStyleName, SFX_STYLE_FAMILY_PARA );
637 : }
638 0 : }
639 : }
640 :
641 0 : pDocument->AddCondFormatData( pNewFormat->GetRange(), nTab, pNewFormat->GetKey() );
642 0 : }
643 0 : }
644 :
645 0 : bool ScTable::InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol )
646 : {
647 0 : if (!ValidCol(nCol))
648 0 : return false;
649 :
650 0 : return aCol[nCol].InitBlockPosition(rBlockPos);
651 : }
652 :
653 0 : void ScTable::CopyFromClip(
654 : sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
655 : SCsCOL nDx, SCsROW nDy, ScTable* pTable )
656 : {
657 :
658 0 : if (nCol2 > MAXCOL)
659 0 : nCol2 = MAXCOL;
660 0 : if (nRow2 > MAXROW)
661 0 : nRow2 = MAXROW;
662 :
663 0 : if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
664 : {
665 0 : for ( SCCOL i = nCol1; i <= nCol2; i++)
666 0 : aCol[i].CopyFromClip(rCxt, nRow1, nRow2, nDy, pTable->aCol[i - nDx]); // notes are handles at column level
667 :
668 0 : if (rCxt.getInsertFlag() & IDF_ATTRIB)
669 : {
670 : // make sure that there are no old references to the cond formats
671 : sal_uInt16 nWhichArray[2];
672 0 : nWhichArray[0] = ATTR_CONDITIONAL;
673 0 : nWhichArray[1] = 0;
674 0 : for ( SCCOL i = nCol1; i <= nCol2; ++i)
675 0 : aCol[i].ClearItems(nRow1, nRow2, nWhichArray);
676 : }
677 :
678 0 : if ((rCxt.getInsertFlag() & IDF_ATTRIB) != 0)
679 : {
680 0 : if (nRow1==0 && nRow2==MAXROW && pColWidth && pTable->pColWidth)
681 0 : for (SCCOL i=nCol1; i<=nCol2; i++)
682 0 : pColWidth[i] = pTable->pColWidth[i-nDx];
683 :
684 0 : if (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pTable->mpRowHeights &&
685 0 : pRowFlags && pTable->pRowFlags)
686 : {
687 0 : CopyRowHeight(*pTable, nRow1, nRow2, -nDy);
688 : // Must copy CR_MANUALSIZE bit too, otherwise pRowHeight doesn't make sense
689 0 : for (SCROW j=nRow1; j<=nRow2; j++)
690 : {
691 0 : if ( pTable->pRowFlags->GetValue(j-nDy) & CR_MANUALSIZE )
692 0 : pRowFlags->OrValue( j, CR_MANUALSIZE);
693 : else
694 0 : pRowFlags->AndValue( j, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
695 : }
696 : }
697 :
698 : // Zellschutz auf geschuetzter Tabelle nicht setzen
699 0 : if (IsProtected() && (rCxt.getInsertFlag() & IDF_ATTRIB))
700 : {
701 0 : ScPatternAttr aPattern(pDocument->GetPool());
702 0 : aPattern.GetItemSet().Put( ScProtectionAttr( false ) );
703 0 : ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
704 : }
705 :
706 : // create deep copies for conditional formatting
707 0 : CopyConditionalFormat( nCol1, nRow1, nCol2, nRow2, nDx, nDy, pTable);
708 : }
709 : }
710 0 : }
711 :
712 :
713 0 : void ScTable::MixData(
714 : sc::MixDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
715 : sal_uInt16 nFunction, bool bSkipEmpty, const ScTable* pSrcTab )
716 : {
717 0 : for (SCCOL i=nCol1; i<=nCol2; i++)
718 0 : aCol[i].MixData(rCxt, nRow1, nRow2, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
719 0 : }
720 :
721 :
722 : // Markierung von diesem Dokument
723 0 : void ScTable::MixMarked(
724 : sc::MixDocContext& rCxt, const ScMarkData& rMark, sal_uInt16 nFunction,
725 : bool bSkipEmpty, const ScTable* pSrcTab )
726 : {
727 0 : for (SCCOL i=0; i<=MAXCOL; i++)
728 0 : aCol[i].MixMarked(rCxt, rMark, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
729 0 : }
730 :
731 : namespace {
732 :
733 : class TransClipHandler
734 : {
735 : ScTable& mrClipTab;
736 : SCTAB mnSrcTab;
737 : SCCOL mnSrcCol;
738 : size_t mnTopRow;
739 : SCROW mnTransRow;
740 : bool mbAsLink;
741 : bool mbWasCut;
742 :
743 0 : ScAddress getDestPos(size_t nRow) const
744 : {
745 0 : return ScAddress(static_cast<SCCOL>(nRow-mnTopRow), mnTransRow, mrClipTab.GetTab());
746 : }
747 :
748 0 : ScFormulaCell* createRefCell(size_t nSrcRow, const ScAddress& rDestPos) const
749 : {
750 0 : ScAddress aSrcPos(mnSrcCol, nSrcRow, mnSrcTab);
751 : ScSingleRefData aRef;
752 0 : aRef.InitAddress(aSrcPos); // Absolute reference.
753 0 : aRef.SetFlag3D(true);
754 :
755 0 : ScTokenArray aArr;
756 0 : aArr.AddSingleReference(aRef);
757 0 : return new ScFormulaCell(&mrClipTab.GetDoc(), rDestPos, aArr);
758 : }
759 :
760 0 : void setLink(size_t nRow)
761 : {
762 0 : SCCOL nTransCol = nRow - mnTopRow;
763 : mrClipTab.SetFormulaCell(
764 0 : nTransCol, mnTransRow, createRefCell(nRow, getDestPos(nRow)));
765 0 : }
766 :
767 : public:
768 0 : TransClipHandler(ScTable& rClipTab, SCTAB nSrcTab, SCCOL nSrcCol, size_t nTopRow, SCROW nTransRow, bool bAsLink, bool bWasCut) :
769 : mrClipTab(rClipTab), mnSrcTab(nSrcTab), mnSrcCol(nSrcCol),
770 0 : mnTopRow(nTopRow), mnTransRow(nTransRow), mbAsLink(bAsLink), mbWasCut(bWasCut) {}
771 :
772 0 : void operator() (size_t nRow, double fVal)
773 : {
774 0 : if (mbAsLink)
775 : {
776 0 : setLink(nRow);
777 0 : return;
778 : }
779 :
780 0 : SCCOL nTransCol = nRow - mnTopRow;
781 0 : mrClipTab.SetValue(nTransCol, mnTransRow, fVal);
782 : }
783 :
784 0 : void operator() (size_t nRow, const svl::SharedString& rStr)
785 : {
786 0 : if (mbAsLink)
787 : {
788 0 : setLink(nRow);
789 0 : return;
790 : }
791 :
792 0 : SCCOL nTransCol = nRow - mnTopRow;
793 0 : mrClipTab.SetRawString(nTransCol, mnTransRow, rStr);
794 : }
795 :
796 0 : void operator() (size_t nRow, const EditTextObject* p)
797 : {
798 0 : if (mbAsLink)
799 : {
800 0 : setLink(nRow);
801 0 : return;
802 : }
803 :
804 0 : SCCOL nTransCol = nRow - mnTopRow;
805 0 : mrClipTab.SetEditText(nTransCol, mnTransRow, ScEditUtil::Clone(*p, mrClipTab.GetDoc()));
806 : }
807 :
808 0 : void operator() (size_t nRow, const ScFormulaCell* p)
809 : {
810 0 : if (mbAsLink)
811 : {
812 0 : setLink(nRow);
813 0 : return;
814 : }
815 :
816 : ScFormulaCell* pNew = new ScFormulaCell(
817 0 : *p, mrClipTab.GetDoc(), getDestPos(nRow), SC_CLONECELL_STARTLISTENING);
818 :
819 : // Referenzen drehen
820 : // bei Cut werden Referenzen spaeter per UpdateTranspose angepasst
821 :
822 0 : if (!mbWasCut)
823 0 : pNew->TransposeReference();
824 :
825 0 : SCCOL nTransCol = nRow - mnTopRow;
826 0 : mrClipTab.SetFormulaCell(nTransCol, mnTransRow, pNew);
827 : }
828 : };
829 :
830 : }
831 :
832 0 : void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
833 : ScTable* pTransClip, sal_uInt16 nFlags, bool bAsLink )
834 : {
835 0 : bool bWasCut = pDocument->IsCutMode();
836 :
837 0 : ScDocument* pDestDoc = pTransClip->pDocument;
838 :
839 0 : for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
840 : {
841 : SCROW nRow;
842 0 : if ( bAsLink && nFlags == IDF_ALL )
843 : {
844 : // with IDF_ALL, also create links (formulas) for empty cells
845 :
846 0 : for ( nRow=nRow1; nRow<=nRow2; nRow++ )
847 : {
848 : // create simple formula, as in ScColumn::CreateRefCell
849 :
850 0 : ScAddress aDestPos( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
851 : ScSingleRefData aRef;
852 0 : aRef.InitAddress(ScAddress(nCol,nRow,nTab));
853 0 : aRef.SetFlag3D(true);
854 0 : ScTokenArray aArr;
855 0 : aArr.AddSingleReference( aRef );
856 :
857 : pTransClip->SetFormulaCell(
858 0 : static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1),
859 0 : new ScFormulaCell(pDestDoc, aDestPos, aArr));
860 0 : }
861 : }
862 : else
863 : {
864 0 : TransClipHandler aFunc(*pTransClip, nTab, nCol, nRow1, static_cast<SCROW>(nCol-nCol1), bAsLink, bWasCut);
865 0 : const sc::CellStoreType& rCells = aCol[nCol].maCells;
866 0 : sc::ParseAllNonEmpty(rCells.begin(), rCells, nRow1, nRow2, aFunc);
867 : }
868 :
869 : // Attribute
870 :
871 : SCROW nAttrRow1;
872 : SCROW nAttrRow2;
873 : const ScPatternAttr* pPattern;
874 0 : boost::scoped_ptr<ScAttrIterator> pAttrIter(aCol[nCol].CreateAttrIterator( nRow1, nRow2 ));
875 0 : while ( (pPattern = pAttrIter->Next( nAttrRow1, nAttrRow2 )) != 0 )
876 : {
877 0 : if ( !IsDefaultItem( pPattern ) )
878 : {
879 0 : const SfxItemSet& rSet = pPattern->GetItemSet();
880 0 : if ( rSet.GetItemState( ATTR_MERGE, false ) == SFX_ITEM_DEFAULT &&
881 0 : rSet.GetItemState( ATTR_MERGE_FLAG, false ) == SFX_ITEM_DEFAULT &&
882 0 : rSet.GetItemState( ATTR_BORDER, false ) == SFX_ITEM_DEFAULT )
883 : {
884 : // no borders or merge items involved - use pattern as-is
885 0 : for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
886 0 : pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), *pPattern, true );
887 : }
888 : else
889 : {
890 : // transpose borders and merge values, remove merge flags (refreshed after pasting)
891 0 : ScPatternAttr aNewPattern( *pPattern );
892 0 : SfxItemSet& rNewSet = aNewPattern.GetItemSet();
893 :
894 0 : const SvxBoxItem& rOldBox = (const SvxBoxItem&)rSet.Get(ATTR_BORDER);
895 0 : if ( rOldBox.GetTop() || rOldBox.GetBottom() || rOldBox.GetLeft() || rOldBox.GetRight() )
896 : {
897 0 : SvxBoxItem aNew( ATTR_BORDER );
898 0 : aNew.SetLine( rOldBox.GetLine( BOX_LINE_TOP ), BOX_LINE_LEFT );
899 0 : aNew.SetLine( rOldBox.GetLine( BOX_LINE_LEFT ), BOX_LINE_TOP );
900 0 : aNew.SetLine( rOldBox.GetLine( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT );
901 0 : aNew.SetLine( rOldBox.GetLine( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM );
902 0 : aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_TOP ), BOX_LINE_LEFT );
903 0 : aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_LEFT ), BOX_LINE_TOP );
904 0 : aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_BOTTOM ), BOX_LINE_RIGHT );
905 0 : aNew.SetDistance( rOldBox.GetDistance( BOX_LINE_RIGHT ), BOX_LINE_BOTTOM );
906 0 : rNewSet.Put( aNew );
907 : }
908 :
909 0 : const ScMergeAttr& rOldMerge = (const ScMergeAttr&)rSet.Get(ATTR_MERGE);
910 0 : if (rOldMerge.IsMerged())
911 : rNewSet.Put( ScMergeAttr( std::min(
912 0 : static_cast<SCsCOL>(rOldMerge.GetRowMerge()),
913 0 : static_cast<SCsCOL>(MAXCOL+1 - (nAttrRow2-nRow1))),
914 : std::min(
915 0 : static_cast<SCsROW>(rOldMerge.GetColMerge()),
916 0 : static_cast<SCsROW>(MAXROW+1 - (nCol-nCol1)))));
917 0 : const ScMergeFlagAttr& rOldFlag = (const ScMergeFlagAttr&)rSet.Get(ATTR_MERGE_FLAG);
918 0 : if (rOldFlag.IsOverlapped())
919 : {
920 0 : sal_Int16 nNewFlags = rOldFlag.GetValue() & ~( SC_MF_HOR | SC_MF_VER );
921 0 : if ( nNewFlags )
922 0 : rNewSet.Put( ScMergeFlagAttr( nNewFlags ) );
923 : else
924 0 : rNewSet.ClearItem( ATTR_MERGE_FLAG );
925 : }
926 :
927 0 : for (nRow = nAttrRow1; nRow<=nAttrRow2; nRow++)
928 : pTransClip->SetPattern( static_cast<SCCOL>(nRow-nRow1),
929 0 : static_cast<SCROW>(nCol-nCol1), aNewPattern, true);
930 : }
931 : }
932 : }
933 :
934 : // Cell Notes - fdo#68381 paste cell notes on Transpose
935 0 : if ( pDocument->HasColNotes(nCol, nTab) )
936 0 : TransposeColNotes(pTransClip, nCol1, nCol, nRow1, nRow2);
937 0 : }
938 0 : }
939 :
940 0 : void ScTable::TransposeColNotes(ScTable* pTransClip, SCCOL nCol1, SCCOL nCol, SCROW nRow1, SCROW nRow2)
941 : {
942 0 : bool bCloneCaption = true;
943 :
944 0 : sc::CellNoteStoreType::const_iterator itBlk = aCol[nCol].maCellNotes.begin(), itBlkEnd = aCol[nCol].maCellNotes.end();
945 :
946 : // Locate the top row position.
947 0 : size_t nOffsetInBlock = 0;
948 0 : size_t nBlockStart = 0, nBlockEnd = 0, nRowPos = static_cast<size_t>(nRow1);
949 0 : for (; itBlk != itBlkEnd; ++itBlk, nBlockStart = nBlockEnd)
950 : {
951 0 : nBlockEnd = nBlockStart + itBlk->size;
952 0 : if (nBlockStart <= nRowPos && nRowPos < nBlockEnd)
953 : {
954 : // Found.
955 0 : nOffsetInBlock = nRowPos - nBlockStart;
956 0 : break;
957 : }
958 : }
959 :
960 0 : if (itBlk != itBlkEnd)
961 : // Specified range found
962 : {
963 0 : nRowPos = static_cast<size_t>(nRow2); // End row position.
964 :
965 : // Keep processing until we hit the end row position.
966 0 : sc::cellnote_block::const_iterator itData, itDataEnd;
967 0 : for (; itBlk != itBlkEnd; ++itBlk, nBlockStart = nBlockEnd, nOffsetInBlock = 0)
968 : {
969 0 : nBlockEnd = nBlockStart + itBlk->size;
970 :
971 0 : if (itBlk->data)
972 : {
973 0 : itData = sc::cellnote_block::begin(*itBlk->data);
974 0 : std::advance(itData, nOffsetInBlock);
975 :
976 0 : if (nBlockStart <= nRowPos && nRowPos < nBlockEnd)
977 : {
978 : // This block contains the end row. Only process partially.
979 0 : size_t nOffsetEnd = nRowPos - nBlockStart + 1;
980 0 : itDataEnd = sc::cellnote_block::begin(*itBlk->data);
981 0 : std::advance(itDataEnd, nOffsetEnd);
982 0 : size_t curRow = nBlockStart + nOffsetInBlock;
983 0 : for (; itData != itDataEnd; ++itData, ++curRow)
984 : {
985 0 : ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
986 0 : pTransClip->pDocument->ReleaseNote(aDestPos);
987 0 : ScPostIt* pNote = *itData;
988 0 : if (pNote)
989 : {
990 0 : ScPostIt* pClonedNote = pNote->Clone( ScAddress(nCol, curRow, nTab), *pTransClip->pDocument, aDestPos, bCloneCaption );
991 0 : pTransClip->pDocument->SetNote(aDestPos, pClonedNote);
992 : }
993 : }
994 0 : break; // we reached the last valid block
995 : }
996 : else
997 : {
998 0 : itDataEnd = sc::cellnote_block::end(*itBlk->data);
999 0 : size_t curRow = nBlockStart + nOffsetInBlock;
1000 0 : for (; itData != itDataEnd; ++itData, ++curRow)
1001 : {
1002 0 : ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
1003 0 : pTransClip->pDocument->ReleaseNote(aDestPos);
1004 0 : ScPostIt* pNote = *itData;
1005 0 : if (pNote)
1006 : {
1007 0 : ScPostIt* pClonedNote = pNote->Clone( ScAddress(nCol, curRow, nTab), *pTransClip->pDocument, aDestPos, bCloneCaption );
1008 0 : pTransClip->pDocument->SetNote(aDestPos, pClonedNote);
1009 : }
1010 : }
1011 : }
1012 : }
1013 : else
1014 : {
1015 : size_t curRow;
1016 0 : for ( curRow = nBlockStart + nOffsetInBlock; curRow <= nBlockEnd && curRow <= nRowPos; ++curRow)
1017 : {
1018 0 : ScAddress aDestPos( static_cast<SCCOL>(curRow-nRow1), static_cast<SCROW>(nCol-nCol1), pTransClip->nTab );
1019 0 : pTransClip->pDocument->ReleaseNote(aDestPos);
1020 : }
1021 0 : if (curRow == nRowPos)
1022 0 : break;
1023 : }
1024 : }
1025 : }
1026 0 : }
1027 :
1028 0 : void ScTable::StartAllListeners()
1029 : {
1030 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1031 0 : aCol[i].StartAllListeners();
1032 0 : }
1033 :
1034 :
1035 0 : void ScTable::StartNeededListeners()
1036 : {
1037 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1038 0 : aCol[i].StartNeededListeners();
1039 0 : }
1040 :
1041 :
1042 0 : void ScTable::BroadcastInArea( SCCOL nCol1, SCROW nRow1,
1043 : SCCOL nCol2, SCROW nRow2 )
1044 : {
1045 0 : if (nCol2 > MAXCOL) nCol2 = MAXCOL;
1046 0 : if (nRow2 > MAXROW) nRow2 = MAXROW;
1047 0 : if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1048 0 : for (SCCOL i = nCol1; i <= nCol2; i++)
1049 0 : aCol[i].SetDirty(nRow1, nRow2);
1050 0 : }
1051 :
1052 :
1053 0 : void ScTable::StartListeningInArea(
1054 : sc::StartListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1055 : {
1056 0 : if (nCol2 > MAXCOL) nCol2 = MAXCOL;
1057 0 : if (nRow2 > MAXROW) nRow2 = MAXROW;
1058 0 : if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1059 0 : for (SCCOL i = nCol1; i <= nCol2; i++)
1060 0 : aCol[i].StartListeningInArea(rCxt, nRow1, nRow2);
1061 0 : }
1062 :
1063 :
1064 0 : void ScTable::CopyToTable(
1065 : sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1066 : sal_uInt16 nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData,
1067 : bool bAsLink, bool bColRowFlags )
1068 : {
1069 0 : if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
1070 0 : return;
1071 :
1072 0 : if (nFlags)
1073 0 : for (SCCOL i = nCol1; i <= nCol2; i++)
1074 0 : aCol[i].CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked,
1075 0 : pDestTab->aCol[i], pMarkData, bAsLink);
1076 :
1077 0 : if (!bColRowFlags) // Spaltenbreiten/Zeilenhoehen/Flags
1078 0 : return;
1079 :
1080 0 : if(pDestTab->pDocument->IsUndo() && (nFlags & IDF_ATTRIB))
1081 : {
1082 0 : pDestTab->mpCondFormatList.reset(new ScConditionalFormatList(pDestTab->pDocument, *mpCondFormatList));
1083 : }
1084 :
1085 0 : if (pDBDataNoName)
1086 : {
1087 0 : ScDBData* pNewDBData = new ScDBData(*pDBDataNoName);
1088 : SCCOL aCol1, aCol2;
1089 : SCROW aRow1, aRow2;
1090 : SCTAB aTab;
1091 0 : pNewDBData->GetArea(aTab, aCol1, aRow1, aCol2, aRow2);
1092 0 : pNewDBData->MoveTo(pDestTab->nTab, aCol1, aRow1, aCol2, aRow2);
1093 0 : pDestTab->SetAnonymousDBData(pNewDBData);
1094 : }
1095 : // Charts muessen beim Ein-/Ausblenden angepasst werden
1096 0 : ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection();
1097 :
1098 0 : bool bFlagChange = false;
1099 :
1100 0 : bool bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
1101 0 : bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights);
1102 :
1103 0 : if (bWidth || bHeight)
1104 : {
1105 0 : if (bWidth)
1106 : {
1107 0 : for (SCCOL i = nCol1; i <= nCol2; ++i)
1108 : {
1109 0 : bool bThisHidden = ColHidden(i);
1110 0 : bool bHiddenChange = (pDestTab->ColHidden(i) != bThisHidden);
1111 0 : bool bChange = bHiddenChange || (pDestTab->pColWidth[i] != pColWidth[i]);
1112 0 : pDestTab->pColWidth[i] = pColWidth[i];
1113 0 : pDestTab->pColFlags[i] = pColFlags[i];
1114 0 : pDestTab->SetColHidden(i, i, bThisHidden);
1115 : //! Aenderungen zusammenfassen?
1116 0 : if (bHiddenChange && pCharts)
1117 0 : pCharts->SetRangeDirty(ScRange( i, 0, nTab, i, MAXROW, nTab ));
1118 :
1119 0 : if (bChange)
1120 0 : bFlagChange = true;
1121 : }
1122 0 : pDestTab->SetColManualBreaks( maColManualBreaks);
1123 : }
1124 :
1125 0 : if (bHeight)
1126 : {
1127 0 : bool bChange = pDestTab->GetRowHeight(nRow1, nRow2) != GetRowHeight(nRow1, nRow2);
1128 :
1129 0 : if (bChange)
1130 0 : bFlagChange = true;
1131 :
1132 0 : pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
1133 0 : pDestTab->pRowFlags->CopyFrom(*pRowFlags, nRow1, nRow2);
1134 :
1135 : // Hidden flags.
1136 0 : for (SCROW i = nRow1; i <= nRow2; ++i)
1137 : {
1138 : SCROW nLastRow;
1139 0 : bool bHidden = RowHidden(i, NULL, &nLastRow);
1140 0 : if (nLastRow >= nRow2)
1141 : // the last row shouldn't exceed the upper bound the caller specified.
1142 0 : nLastRow = nRow2;
1143 :
1144 0 : bool bHiddenChanged = pDestTab->SetRowHidden(i, nLastRow, bHidden);
1145 0 : if (bHiddenChanged && pCharts)
1146 : // Hidden flags differ.
1147 0 : pCharts->SetRangeDirty(ScRange(0, i, nTab, MAXCOL, nLastRow, nTab));
1148 :
1149 0 : if (bHiddenChanged)
1150 0 : bFlagChange = true;
1151 :
1152 : // Jump to the last row of the identical flag segment.
1153 0 : i = nLastRow;
1154 : }
1155 :
1156 : // Filtered flags.
1157 0 : for (SCROW i = nRow1; i <= nRow2; ++i)
1158 : {
1159 : SCROW nLastRow;
1160 0 : bool bFiltered = RowFiltered(i, NULL, &nLastRow);
1161 0 : if (nLastRow >= nRow2)
1162 : // the last row shouldn't exceed the upper bound the caller specified.
1163 0 : nLastRow = nRow2;
1164 0 : pDestTab->SetRowFiltered(i, nLastRow, bFiltered);
1165 0 : i = nLastRow;
1166 : }
1167 0 : pDestTab->SetRowManualBreaks( maRowManualBreaks);
1168 : }
1169 : }
1170 :
1171 0 : if (bFlagChange)
1172 0 : pDestTab->InvalidatePageBreaks();
1173 :
1174 0 : if(nFlags & IDF_ATTRIB)
1175 : {
1176 0 : pDestTab->mpCondFormatList->DeleteArea(nCol1, nRow1, nCol2, nRow2);
1177 0 : pDestTab->CopyConditionalFormat(nCol1, nRow1, nCol2, nRow2, 0, 0, this);
1178 : }
1179 :
1180 0 : if(nFlags & IDF_OUTLINE) // also only when bColRowFlags
1181 0 : pDestTab->SetOutlineTable( pOutlineTable );
1182 : }
1183 :
1184 :
1185 0 : void ScTable::UndoToTable(
1186 : sc::CopyToDocContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1187 : sal_uInt16 nFlags, bool bMarked, ScTable* pDestTab, const ScMarkData* pMarkData )
1188 : {
1189 0 : if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2))
1190 : {
1191 0 : bool bWidth = (nRow1==0 && nRow2==MAXROW && pColWidth && pDestTab->pColWidth);
1192 0 : bool bHeight = (nCol1==0 && nCol2==MAXCOL && mpRowHeights && pDestTab->mpRowHeights);
1193 :
1194 0 : for ( SCCOL i = 0; i <= MAXCOL; i++)
1195 : {
1196 0 : if ( i >= nCol1 && i <= nCol2 )
1197 0 : aCol[i].UndoToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, pDestTab->aCol[i], pMarkData);
1198 : else
1199 0 : aCol[i].CopyToColumn(rCxt, 0, MAXROW, IDF_FORMULA, false, pDestTab->aCol[i]);
1200 : }
1201 :
1202 0 : if (nFlags & IDF_ATTRIB)
1203 0 : pDestTab->mpCondFormatList.reset(new ScConditionalFormatList(pDestTab->pDocument, *mpCondFormatList));
1204 :
1205 :
1206 0 : if (bWidth||bHeight)
1207 : {
1208 0 : if (bWidth)
1209 : {
1210 0 : for (SCCOL i=nCol1; i<=nCol2; i++)
1211 0 : pDestTab->pColWidth[i] = pColWidth[i];
1212 0 : pDestTab->SetColManualBreaks( maColManualBreaks);
1213 : }
1214 0 : if (bHeight)
1215 : {
1216 0 : pDestTab->CopyRowHeight(*this, nRow1, nRow2, 0);
1217 0 : pDestTab->SetRowManualBreaks( maRowManualBreaks);
1218 : }
1219 : }
1220 : }
1221 0 : }
1222 :
1223 :
1224 0 : void ScTable::CopyUpdated( const ScTable* pPosTab, ScTable* pDestTab ) const
1225 : {
1226 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1227 0 : aCol[i].CopyUpdated( pPosTab->aCol[i], pDestTab->aCol[i] );
1228 0 : }
1229 :
1230 0 : void ScTable::InvalidateTableArea()
1231 : {
1232 0 : bTableAreaValid = false;
1233 0 : }
1234 :
1235 0 : void ScTable::InvalidatePageBreaks()
1236 : {
1237 0 : mbPageBreaksValid = false;
1238 0 : }
1239 :
1240 0 : void ScTable::CopyScenarioTo( ScTable* pDestTab ) const
1241 : {
1242 : OSL_ENSURE( bScenario, "bScenario == FALSE" );
1243 :
1244 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1245 0 : aCol[i].CopyScenarioTo( pDestTab->aCol[i] );
1246 0 : }
1247 :
1248 0 : void ScTable::CopyScenarioFrom( const ScTable* pSrcTab )
1249 : {
1250 : OSL_ENSURE( bScenario, "bScenario == FALSE" );
1251 :
1252 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1253 0 : aCol[i].CopyScenarioFrom( pSrcTab->aCol[i] );
1254 0 : }
1255 :
1256 0 : void ScTable::MarkScenarioIn( ScMarkData& rDestMark, sal_uInt16 nNeededBits ) const
1257 : {
1258 : OSL_ENSURE( bScenario, "bScenario == FALSE" );
1259 :
1260 0 : if ( ( nScenarioFlags & nNeededBits ) != nNeededBits ) // alle Bits gesetzt?
1261 0 : return;
1262 :
1263 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1264 0 : aCol[i].MarkScenarioIn( rDestMark );
1265 : }
1266 :
1267 0 : bool ScTable::HasScenarioRange( const ScRange& rRange ) const
1268 : {
1269 : OSL_ENSURE( bScenario, "bScenario == FALSE" );
1270 :
1271 0 : ScRange aTabRange = rRange;
1272 0 : aTabRange.aStart.SetTab( nTab );
1273 0 : aTabRange.aEnd.SetTab( nTab );
1274 :
1275 0 : const ScRangeList* pList = GetScenarioRanges();
1276 :
1277 0 : if (pList)
1278 : {
1279 0 : for ( size_t j = 0, n = pList->size(); j < n; j++ )
1280 : {
1281 0 : const ScRange* pR = (*pList)[j];
1282 0 : if ( pR->Intersects( aTabRange ) )
1283 0 : return true;
1284 : }
1285 : }
1286 :
1287 0 : return false;
1288 : }
1289 :
1290 0 : void ScTable::InvalidateScenarioRanges()
1291 : {
1292 0 : delete pScenarioRanges;
1293 0 : pScenarioRanges = NULL;
1294 0 : }
1295 :
1296 0 : const ScRangeList* ScTable::GetScenarioRanges() const
1297 : {
1298 : OSL_ENSURE( bScenario, "bScenario == FALSE" );
1299 :
1300 0 : if (!pScenarioRanges)
1301 : {
1302 0 : ((ScTable*)this)->pScenarioRanges = new ScRangeList;
1303 0 : ScMarkData aMark;
1304 0 : MarkScenarioIn( aMark, 0 ); // immer
1305 0 : aMark.FillRangeListWithMarks( pScenarioRanges, false );
1306 : }
1307 0 : return pScenarioRanges;
1308 : }
1309 :
1310 0 : bool ScTable::TestCopyScenarioTo( const ScTable* pDestTab ) const
1311 : {
1312 : OSL_ENSURE( bScenario, "bScenario == FALSE" );
1313 :
1314 0 : if (!pDestTab->IsProtected())
1315 0 : return true;
1316 :
1317 0 : bool bOk = true;
1318 0 : for (SCCOL i=0; i<=MAXCOL && bOk; i++)
1319 0 : bOk = aCol[i].TestCopyScenarioTo( pDestTab->aCol[i] );
1320 0 : return bOk;
1321 : }
1322 :
1323 0 : bool ScTable::SetString( SCCOL nCol, SCROW nRow, SCTAB nTabP, const OUString& rString,
1324 : ScSetStringParam* pParam )
1325 : {
1326 0 : if (ValidColRow(nCol,nRow))
1327 0 : return aCol[nCol].SetString(
1328 0 : nRow, nTabP, rString, pDocument->GetAddressConvention(), pParam );
1329 : else
1330 0 : return false;
1331 : }
1332 :
1333 0 : void ScTable::SetEditText( SCCOL nCol, SCROW nRow, EditTextObject* pEditText )
1334 : {
1335 0 : if (!ValidColRow(nCol, nRow))
1336 : {
1337 0 : delete pEditText;
1338 0 : return;
1339 : }
1340 :
1341 0 : aCol[nCol].SetEditText(nRow, pEditText);
1342 : }
1343 :
1344 0 : void ScTable::SetEditText( SCCOL nCol, SCROW nRow, const EditTextObject& rEditText, const SfxItemPool* pEditPool )
1345 : {
1346 0 : if (!ValidColRow(nCol, nRow))
1347 0 : return;
1348 :
1349 0 : aCol[nCol].SetEditText(nRow, rEditText, pEditPool);
1350 : }
1351 :
1352 0 : SCROW ScTable::GetFirstEditTextRow( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
1353 : {
1354 0 : if (!ValidCol(nCol1) || !ValidCol(nCol2) || nCol2 < nCol1)
1355 0 : return -1;
1356 :
1357 0 : if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow2 < nRow1)
1358 0 : return -1;
1359 :
1360 0 : SCROW nFirst = MAXROW+1;
1361 0 : for (SCCOL i = nCol1; i <= nCol2; ++i)
1362 : {
1363 0 : const ScColumn& rCol = aCol[i];
1364 0 : SCROW nThisFirst = -1;
1365 0 : if (const_cast<ScColumn&>(rCol).HasEditCells(nRow1, nRow2, nThisFirst))
1366 : {
1367 0 : if (nThisFirst == nRow1)
1368 0 : return nRow1;
1369 :
1370 0 : if (nThisFirst < nFirst)
1371 0 : nFirst = nThisFirst;
1372 : }
1373 : }
1374 :
1375 0 : return nFirst == (MAXROW+1) ? -1 : nFirst;
1376 : }
1377 :
1378 0 : void ScTable::SetEmptyCell( SCCOL nCol, SCROW nRow )
1379 : {
1380 0 : if (!ValidColRow(nCol, nRow))
1381 0 : return;
1382 :
1383 0 : aCol[nCol].Delete(nRow);
1384 : }
1385 :
1386 0 : void ScTable::SetFormula(
1387 : SCCOL nCol, SCROW nRow, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram )
1388 : {
1389 0 : if (!ValidColRow(nCol, nRow))
1390 0 : return;
1391 :
1392 0 : aCol[nCol].SetFormula(nRow, rArray, eGram);
1393 : }
1394 :
1395 0 : void ScTable::SetFormula(
1396 : SCCOL nCol, SCROW nRow, const OUString& rFormula, formula::FormulaGrammar::Grammar eGram )
1397 : {
1398 0 : if (!ValidColRow(nCol, nRow))
1399 0 : return;
1400 :
1401 0 : aCol[nCol].SetFormula(nRow, rFormula, eGram);
1402 : }
1403 :
1404 0 : ScFormulaCell* ScTable::SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell )
1405 : {
1406 0 : if (!ValidColRow(nCol, nRow))
1407 : {
1408 0 : delete pCell;
1409 0 : return NULL;
1410 : }
1411 :
1412 0 : return aCol[nCol].SetFormulaCell(nRow, pCell);
1413 : }
1414 :
1415 0 : bool ScTable::SetFormulaCells( SCCOL nCol, SCROW nRow, std::vector<ScFormulaCell*>& rCells )
1416 : {
1417 0 : if (!ValidCol(nCol))
1418 0 : return false;
1419 :
1420 0 : return aCol[nCol].SetFormulaCells(nRow, rCells);
1421 : }
1422 :
1423 0 : svl::SharedString ScTable::GetSharedString( SCCOL nCol, SCROW nRow ) const
1424 : {
1425 0 : if (!ValidColRow(nCol, nRow))
1426 0 : return svl::SharedString();
1427 :
1428 0 : return aCol[nCol].GetSharedString(nRow);
1429 : }
1430 :
1431 0 : void ScTable::SetValue( SCCOL nCol, SCROW nRow, const double& rVal )
1432 : {
1433 0 : if (ValidColRow(nCol, nRow))
1434 0 : aCol[nCol].SetValue( nRow, rVal );
1435 0 : }
1436 :
1437 0 : void ScTable::SetRawString( SCCOL nCol, SCROW nRow, const svl::SharedString& rStr )
1438 : {
1439 0 : if (ValidColRow(nCol, nRow))
1440 0 : aCol[nCol].SetRawString(nRow, rStr);
1441 0 : }
1442 :
1443 0 : void ScTable::GetString( SCCOL nCol, SCROW nRow, OUString& rString ) const
1444 : {
1445 0 : if (ValidColRow(nCol,nRow))
1446 0 : aCol[nCol].GetString( nRow, rString );
1447 : else
1448 0 : rString = OUString();
1449 0 : }
1450 :
1451 0 : double* ScTable::GetValueCell( SCCOL nCol, SCROW nRow )
1452 : {
1453 0 : if (!ValidColRow(nCol,nRow))
1454 0 : return NULL;
1455 :
1456 0 : return aCol[nCol].GetValueCell(nRow);
1457 : }
1458 :
1459 0 : void ScTable::GetInputString( SCCOL nCol, SCROW nRow, OUString& rString ) const
1460 : {
1461 0 : if (ValidColRow(nCol,nRow))
1462 0 : aCol[nCol].GetInputString( nRow, rString );
1463 : else
1464 0 : rString = OUString();
1465 0 : }
1466 :
1467 :
1468 0 : double ScTable::GetValue( SCCOL nCol, SCROW nRow ) const
1469 : {
1470 0 : if (ValidColRow( nCol, nRow ))
1471 0 : return aCol[nCol].GetValue( nRow );
1472 0 : return 0.0;
1473 : }
1474 :
1475 0 : const EditTextObject* ScTable::GetEditText( SCCOL nCol, SCROW nRow ) const
1476 : {
1477 0 : if (!ValidColRow(nCol, nRow))
1478 0 : return NULL;
1479 :
1480 0 : return aCol[nCol].GetEditText(nRow);
1481 : }
1482 :
1483 0 : void ScTable::RemoveEditTextCharAttribs( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
1484 : {
1485 0 : if (!ValidColRow(nCol, nRow))
1486 0 : return;
1487 :
1488 0 : return aCol[nCol].RemoveEditTextCharAttribs(nRow, rAttr);
1489 : }
1490 :
1491 0 : void ScTable::GetFormula( SCCOL nCol, SCROW nRow, OUString& rFormula ) const
1492 : {
1493 0 : if (ValidColRow(nCol,nRow))
1494 0 : aCol[nCol].GetFormula( nRow, rFormula );
1495 : else
1496 0 : rFormula = OUString();
1497 0 : }
1498 :
1499 0 : const ScFormulaCell* ScTable::GetFormulaCell( SCCOL nCol, SCROW nRow ) const
1500 : {
1501 0 : if (!ValidColRow(nCol, nRow))
1502 0 : return NULL;
1503 :
1504 0 : return aCol[nCol].GetFormulaCell(nRow);
1505 : }
1506 :
1507 0 : ScFormulaCell* ScTable::GetFormulaCell( SCCOL nCol, SCROW nRow )
1508 : {
1509 0 : if (!ValidColRow(nCol, nRow))
1510 0 : return NULL;
1511 :
1512 0 : return aCol[nCol].GetFormulaCell(nRow);
1513 : }
1514 :
1515 0 : ScPostIt* ScTable::ReleaseNote( SCCOL nCol, SCROW nRow )
1516 : {
1517 0 : if (!ValidCol(nCol))
1518 0 : return NULL;
1519 :
1520 0 : return aCol[nCol].ReleaseNote(nRow);
1521 : }
1522 :
1523 0 : size_t ScTable::GetNoteCount( SCCOL nCol ) const
1524 : {
1525 0 : if (!ValidCol(nCol))
1526 0 : return 0;
1527 :
1528 0 : return aCol[nCol].GetNoteCount();
1529 : }
1530 :
1531 0 : SCROW ScTable::GetNotePosition( SCCOL nCol, size_t nIndex ) const
1532 : {
1533 0 : if (!ValidCol(nCol))
1534 0 : return -1;
1535 :
1536 0 : return aCol[nCol].GetNotePosition(nIndex);
1537 : }
1538 :
1539 0 : void ScTable::CreateAllNoteCaptions()
1540 : {
1541 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
1542 0 : aCol[i].CreateAllNoteCaptions();
1543 0 : }
1544 :
1545 0 : void ScTable::ForgetNoteCaptions( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
1546 : {
1547 0 : if (!ValidCol(nCol1) || !ValidCol(nCol2))
1548 0 : return;
1549 :
1550 0 : for (SCCOL i = nCol1; i <= nCol2; ++i)
1551 0 : aCol[i].ForgetNoteCaptions(nRow1, nRow2);
1552 : }
1553 :
1554 0 : void ScTable::GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) const
1555 : {
1556 0 : for (SCCOL nCol = 0; nCol < MAXCOLCOUNT; ++nCol)
1557 0 : aCol[nCol].GetAllNoteEntries(rNotes);
1558 0 : }
1559 :
1560 0 : void ScTable::GetNotesInRange( const ScRange& rRange, std::vector<sc::NoteEntry>& rNotes ) const
1561 : {
1562 0 : SCROW nStartRow = rRange.aStart.Row();
1563 0 : SCROW nEndRow = rRange.aEnd.Row();
1564 0 : for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1565 : {
1566 0 : aCol[nCol].GetNotesInRange(nStartRow, nEndRow, rNotes);
1567 : }
1568 0 : }
1569 :
1570 0 : bool ScTable::ContainsNotesInRange( const ScRange& rRange ) const
1571 : {
1572 0 : SCROW nStartRow = rRange.aStart.Row();
1573 0 : SCROW nEndRow = rRange.aEnd.Row();
1574 0 : for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1575 : {
1576 0 : bool bContainsNote = !aCol[nCol].IsNotesEmptyBlock(nStartRow, nEndRow);
1577 0 : if(bContainsNote)
1578 0 : return true;
1579 : }
1580 :
1581 0 : return false;
1582 : }
1583 :
1584 0 : CellType ScTable::GetCellType( SCCOL nCol, SCROW nRow ) const
1585 : {
1586 0 : if (ValidColRow( nCol, nRow ))
1587 0 : return aCol[nCol].GetCellType( nRow );
1588 0 : return CELLTYPE_NONE;
1589 : }
1590 :
1591 0 : ScRefCellValue ScTable::GetCellValue( SCCOL nCol, SCROW nRow ) const
1592 : {
1593 0 : if (!ValidColRow(nCol, nRow))
1594 0 : return ScRefCellValue();
1595 :
1596 0 : return aCol[nCol].GetCellValue(nRow);
1597 : }
1598 :
1599 0 : void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const
1600 : {
1601 0 : rCol = 0;
1602 0 : rRow = MAXROW+1;
1603 0 : while (aCol[rCol].IsEmptyData() && rCol < MAXCOL)
1604 0 : ++rCol;
1605 0 : SCCOL nCol = rCol;
1606 0 : while (nCol <= MAXCOL && rRow > 0)
1607 : {
1608 0 : if (!aCol[nCol].IsEmptyData())
1609 0 : rRow = ::std::min( rRow, aCol[nCol].GetFirstDataPos());
1610 0 : ++nCol;
1611 : }
1612 0 : }
1613 :
1614 0 : void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
1615 : {
1616 0 : rCol = MAXCOL;
1617 0 : rRow = 0;
1618 0 : while (aCol[rCol].IsEmptyData() && (rCol > 0))
1619 0 : rCol--;
1620 0 : SCCOL nCol = rCol;
1621 0 : while (nCol >= 0 && rRow < MAXROW)
1622 0 : rRow = ::std::max( rRow, aCol[nCol--].GetLastDataPos());
1623 0 : }
1624 :
1625 :
1626 0 : bool ScTable::HasData( SCCOL nCol, SCROW nRow ) const
1627 : {
1628 0 : if (ValidColRow(nCol,nRow))
1629 0 : return aCol[nCol].HasDataAt( nRow );
1630 : else
1631 0 : return false;
1632 : }
1633 :
1634 :
1635 0 : bool ScTable::HasStringData( SCCOL nCol, SCROW nRow ) const
1636 : {
1637 0 : if (ValidColRow(nCol,nRow))
1638 0 : return aCol[nCol].HasStringData( nRow );
1639 : else
1640 0 : return false;
1641 : }
1642 :
1643 :
1644 0 : bool ScTable::HasValueData( SCCOL nCol, SCROW nRow ) const
1645 : {
1646 0 : if (ValidColRow(nCol,nRow))
1647 0 : return aCol[nCol].HasValueData( nRow );
1648 : else
1649 0 : return false;
1650 : }
1651 :
1652 :
1653 0 : bool ScTable::HasStringCells( SCCOL nStartCol, SCROW nStartRow,
1654 : SCCOL nEndCol, SCROW nEndRow ) const
1655 : {
1656 0 : if ( ValidCol(nEndCol) )
1657 0 : for ( SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++ )
1658 0 : if (aCol[nCol].HasStringCells(nStartRow, nEndRow))
1659 0 : return true;
1660 :
1661 0 : return false;
1662 : }
1663 :
1664 :
1665 0 : void ScTable::SetDirtyVar()
1666 : {
1667 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1668 0 : aCol[i].SetDirtyVar();
1669 0 : }
1670 :
1671 :
1672 0 : void ScTable::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt )
1673 : {
1674 0 : sc::AutoCalcSwitch aACSwitch(*pDocument, false);
1675 :
1676 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1677 0 : aCol[i].SetAllFormulasDirty(rCxt);
1678 0 : }
1679 :
1680 :
1681 0 : void ScTable::SetDirty( const ScRange& rRange )
1682 : {
1683 0 : bool bOldAutoCalc = pDocument->GetAutoCalc();
1684 0 : pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
1685 0 : SCCOL nCol2 = rRange.aEnd.Col();
1686 0 : for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
1687 0 : aCol[i].SetDirty(rRange.aStart.Row(), rRange.aEnd.Row());
1688 0 : pDocument->SetAutoCalc( bOldAutoCalc );
1689 0 : }
1690 :
1691 :
1692 0 : void ScTable::SetTableOpDirty( const ScRange& rRange )
1693 : {
1694 0 : bool bOldAutoCalc = pDocument->GetAutoCalc();
1695 0 : pDocument->SetAutoCalc( false ); // no multiple recalculation
1696 0 : SCCOL nCol2 = rRange.aEnd.Col();
1697 0 : for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
1698 0 : aCol[i].SetTableOpDirty( rRange );
1699 0 : pDocument->SetAutoCalc( bOldAutoCalc );
1700 0 : }
1701 :
1702 :
1703 0 : void ScTable::SetDirtyAfterLoad()
1704 : {
1705 0 : bool bOldAutoCalc = pDocument->GetAutoCalc();
1706 0 : pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
1707 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1708 0 : aCol[i].SetDirtyAfterLoad();
1709 0 : pDocument->SetAutoCalc( bOldAutoCalc );
1710 0 : }
1711 :
1712 :
1713 0 : void ScTable::SetDirtyIfPostponed()
1714 : {
1715 0 : bool bOldAutoCalc = pDocument->GetAutoCalc();
1716 0 : pDocument->SetAutoCalc( false ); // Mehrfachberechnungen vermeiden
1717 0 : for (SCCOL i=0; i<=MAXCOL; i++)
1718 0 : aCol[i].SetDirtyIfPostponed();
1719 0 : pDocument->SetAutoCalc( bOldAutoCalc );
1720 0 : }
1721 :
1722 0 : void ScTable::BroadcastRecalcOnRefMove()
1723 : {
1724 0 : sc::AutoCalcSwitch aSwitch(*pDocument, false);
1725 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
1726 0 : aCol[i].BroadcastRecalcOnRefMove();
1727 0 : }
1728 :
1729 0 : void ScTable::BroadcastRefMoved( const sc::RefMovedHint& rHint )
1730 : {
1731 0 : const ScRange& rRange = rHint.getRange();
1732 0 : for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
1733 0 : aCol[nCol].BroadcastRefMoved(rHint);
1734 0 : }
1735 :
1736 0 : void ScTable::TransferListeners(
1737 : ScTable& rDestTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1738 : SCCOL nColDelta, SCROW nRowDelta )
1739 : {
1740 0 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
1741 : {
1742 0 : ScColumn& rSrcCol = aCol[nCol];
1743 0 : ScColumn& rDestCol = rDestTab.aCol[nCol+nColDelta];
1744 0 : rSrcCol.TransferListeners(rDestCol, nRow1, nRow2, nRowDelta);
1745 : }
1746 0 : }
1747 :
1748 0 : void ScTable::SetLoadingMedium(bool bLoading)
1749 : {
1750 0 : mpRowHeights->enableTreeSearch(!bLoading);
1751 0 : }
1752 :
1753 :
1754 0 : void ScTable::CalcAll()
1755 : {
1756 0 : for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CalcAll();
1757 0 : }
1758 :
1759 :
1760 0 : void ScTable::CompileAll( sc::CompileFormulaContext& rCxt )
1761 : {
1762 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
1763 0 : aCol[i].CompileAll(rCxt);
1764 :
1765 0 : if(mpCondFormatList)
1766 0 : mpCondFormatList->CompileAll();
1767 0 : }
1768 :
1769 :
1770 0 : void ScTable::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress )
1771 : {
1772 0 : if (mpRangeName)
1773 0 : mpRangeName->CompileUnresolvedXML(rCxt);
1774 :
1775 0 : for (SCCOL i=0; i <= MAXCOL; i++)
1776 : {
1777 0 : aCol[i].CompileXML(rCxt, rProgress);
1778 : }
1779 :
1780 0 : if(mpCondFormatList)
1781 0 : mpCondFormatList->CompileXML();
1782 0 : }
1783 :
1784 0 : bool ScTable::CompileErrorCells( sc::CompileFormulaContext& rCxt, sal_uInt16 nErrCode )
1785 : {
1786 0 : bool bCompiled = false;
1787 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
1788 : {
1789 0 : if (aCol[i].CompileErrorCells(rCxt, nErrCode))
1790 0 : bCompiled = true;
1791 : }
1792 :
1793 0 : return bCompiled;
1794 : }
1795 :
1796 0 : void ScTable::CalcAfterLoad( sc::CompileFormulaContext& rCxt )
1797 : {
1798 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
1799 0 : aCol[i].CalcAfterLoad(rCxt);
1800 0 : }
1801 :
1802 0 : void ScTable::ResetChanged( const ScRange& rRange )
1803 : {
1804 0 : SCCOL nStartCol = rRange.aStart.Col();
1805 0 : SCROW nStartRow = rRange.aStart.Row();
1806 0 : SCCOL nEndCol = rRange.aEnd.Col();
1807 0 : SCROW nEndRow = rRange.aEnd.Row();
1808 :
1809 0 : for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
1810 0 : aCol[nCol].ResetChanged(nStartRow, nEndRow);
1811 0 : }
1812 :
1813 : // Attribute
1814 :
1815 0 : const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) const
1816 : {
1817 0 : if (ValidColRow(nCol,nRow))
1818 0 : return aCol[nCol].GetAttr( nRow, nWhich );
1819 : else
1820 0 : return NULL;
1821 : }
1822 :
1823 0 : sal_uInt32 ScTable::GetNumberFormat( const ScAddress& rPos ) const
1824 : {
1825 0 : return ValidColRow(rPos.Col(),rPos.Row()) ?
1826 0 : aCol[rPos.Col()].GetNumberFormat( rPos.Row() ) :
1827 0 : 0;
1828 : }
1829 :
1830 0 : sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nRow ) const
1831 : {
1832 0 : if (ValidColRow(nCol,nRow))
1833 0 : return aCol[nCol].GetNumberFormat( nRow );
1834 : else
1835 0 : return 0;
1836 : }
1837 :
1838 0 : sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
1839 : {
1840 0 : if (!ValidCol(nCol) || !ValidRow(nStartRow) || !ValidRow(nEndRow))
1841 0 : return 0;
1842 :
1843 0 : return aCol[nCol].GetNumberFormat(nStartRow, nEndRow);
1844 : }
1845 :
1846 0 : void ScTable::SetNumberFormat( SCCOL nCol, SCROW nRow, sal_uInt32 nNumberFormat )
1847 : {
1848 0 : if (!ValidColRow(nCol, nRow))
1849 0 : return;
1850 :
1851 0 : aCol[nCol].SetNumberFormat(nRow, nNumberFormat);
1852 : }
1853 :
1854 0 : const ScPatternAttr* ScTable::GetPattern( SCCOL nCol, SCROW nRow ) const
1855 : {
1856 0 : if (ValidColRow(nCol,nRow))
1857 0 : return aCol[nCol].GetPattern( nRow );
1858 : else
1859 : {
1860 : OSL_FAIL("wrong column or row");
1861 0 : return pDocument->GetDefPattern(); // for safety
1862 : }
1863 : }
1864 :
1865 :
1866 0 : const ScPatternAttr* ScTable::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const
1867 : {
1868 0 : if ( ValidColRow( nCol, nStartRow ) && ValidRow( nEndRow ) && (nStartRow <= nEndRow) )
1869 0 : return aCol[nCol].GetMostUsedPattern( nStartRow, nEndRow );
1870 : else
1871 0 : return NULL;
1872 : }
1873 :
1874 :
1875 0 : bool ScTable::HasAttrib( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nMask ) const
1876 : {
1877 0 : bool bFound = false;
1878 0 : for (SCCOL i=nCol1; i<=nCol2 && !bFound; i++)
1879 0 : bFound |= aCol[i].HasAttrib( nRow1, nRow2, nMask );
1880 0 : return bFound;
1881 : }
1882 :
1883 :
1884 0 : bool ScTable::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
1885 : {
1886 0 : bool bFound = false;
1887 0 : for (SCCOL i=0; i<=MAXCOL && !bFound; i++)
1888 0 : bFound |= aCol[i].HasAttribSelection( rMark, nMask );
1889 0 : return bFound;
1890 : }
1891 :
1892 :
1893 0 : bool ScTable::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
1894 : SCCOL& rEndCol, SCROW& rEndRow,
1895 : bool bRefresh )
1896 : {
1897 0 : if (!(ValidCol(nStartCol) && ValidCol(rEndCol)))
1898 : {
1899 : OSL_FAIL("ScTable::ExtendMerge: invalid column number");
1900 0 : return false;
1901 : }
1902 0 : bool bFound = false;
1903 0 : SCCOL nOldEndX = rEndCol;
1904 0 : SCROW nOldEndY = rEndRow;
1905 0 : for (SCCOL i=nStartCol; i<=nOldEndX; i++)
1906 0 : bFound |= aCol[i].ExtendMerge( i, nStartRow, nOldEndY, rEndCol, rEndRow, bRefresh );
1907 0 : return bFound;
1908 : }
1909 :
1910 :
1911 0 : bool ScTable::IsBlockEmpty( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bIgnoreNotes ) const
1912 : {
1913 0 : if (!(ValidCol(nCol1) && ValidCol(nCol2)))
1914 : {
1915 : OSL_FAIL("ScTable::IsBlockEmpty: invalid column number");
1916 0 : return false;
1917 : }
1918 0 : bool bEmpty = true;
1919 0 : for (SCCOL i=nCol1; i<=nCol2 && bEmpty; i++)
1920 : {
1921 0 : bEmpty = aCol[i].IsEmptyBlock( nRow1, nRow2 );
1922 0 : if (!bIgnoreNotes && bEmpty)
1923 : {
1924 0 : bEmpty = aCol[i].IsNotesEmptyBlock(nRow1, nRow2);
1925 : }
1926 : }
1927 0 : return bEmpty;
1928 : }
1929 :
1930 0 : SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2,
1931 : SCCOL nCol, SCROW nAttrRow1, SCROW nAttrRow2, SCSIZE nArrY,
1932 : const ScPatternAttr* pPattern, const SfxItemSet* pCondSet )
1933 : {
1934 : // Rueckgabe = neues nArrY
1935 :
1936 0 : sal_uInt8 nRotDir = pPattern->GetRotateDir( pCondSet );
1937 0 : if ( nRotDir != SC_ROTDIR_NONE )
1938 : {
1939 0 : bool bHit = true;
1940 0 : if ( nCol+1 < nX1 ) // column to the left
1941 0 : bHit = ( nRotDir != SC_ROTDIR_LEFT );
1942 0 : else if ( nCol > nX2+1 ) // column to the right
1943 0 : bHit = ( nRotDir != SC_ROTDIR_RIGHT ); // SC_ROTDIR_STANDARD may now also be extended to the left
1944 :
1945 0 : if ( bHit )
1946 : {
1947 0 : double nFactor = 0.0;
1948 0 : if ( nCol > nX2+1 )
1949 : {
1950 : long nRotVal = ((const SfxInt32Item&) pPattern->
1951 0 : GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue();
1952 0 : double nRealOrient = nRotVal * F_PI18000; // 1/100 Grad
1953 0 : double nCos = cos( nRealOrient );
1954 0 : double nSin = sin( nRealOrient );
1955 : //! begrenzen !!!
1956 : //! zusaetzlich Faktor fuer unterschiedliche PPT X/Y !!!
1957 :
1958 : // bei SC_ROTDIR_LEFT kommt immer ein negativer Wert heraus,
1959 : // wenn der Modus beruecksichtigt wird
1960 0 : nFactor = -fabs( nCos / nSin );
1961 : }
1962 :
1963 0 : for ( SCROW nRow = nAttrRow1; nRow <= nAttrRow2; nRow++ )
1964 : {
1965 0 : if (!RowHidden(nRow))
1966 : {
1967 0 : bool bHitOne = true;
1968 0 : if ( nCol > nX2+1 )
1969 : {
1970 : // reicht die gedrehte Zelle bis in den sichtbaren Bereich?
1971 :
1972 0 : SCCOL nTouchedCol = nCol;
1973 0 : long nWidth = static_cast<long>(mpRowHeights->getValue(nRow) * nFactor);
1974 : OSL_ENSURE(nWidth <= 0, "Wrong direction");
1975 0 : while ( nWidth < 0 && nTouchedCol > 0 )
1976 : {
1977 0 : --nTouchedCol;
1978 0 : nWidth += GetColWidth( nTouchedCol );
1979 : }
1980 0 : if ( nTouchedCol > nX2 )
1981 0 : bHitOne = false;
1982 : }
1983 :
1984 0 : if (bHitOne)
1985 : {
1986 0 : while ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo < nRow )
1987 0 : ++nArrY;
1988 0 : if ( nArrY<nArrCount && pRowInfo[nArrY].nRowNo == nRow )
1989 0 : pRowInfo[nArrY].nRotMaxCol = nCol;
1990 : }
1991 : }
1992 : }
1993 : }
1994 : }
1995 :
1996 0 : return nArrY;
1997 : }
1998 :
1999 0 : void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 )
2000 : {
2001 0 : if ( !pColWidth || !mpRowHeights || !pColFlags || !pRowFlags )
2002 : {
2003 : OSL_FAIL( "Row/column info missing" );
2004 0 : return;
2005 : }
2006 :
2007 : // nRotMaxCol ist auf SC_ROTMAX_NONE initialisiert, nRowNo ist schon gesetzt
2008 :
2009 0 : SCROW nY1 = pRowInfo[0].nRowNo;
2010 0 : SCROW nY2 = pRowInfo[nArrCount-1].nRowNo;
2011 :
2012 0 : for (SCCOL nCol=0; nCol<=MAXCOL; nCol++)
2013 : {
2014 0 : if (!ColHidden(nCol))
2015 : {
2016 0 : SCSIZE nArrY = 0;
2017 0 : ScDocAttrIterator aIter( pDocument, nTab, nCol, nY1, nCol, nY2 );
2018 : SCCOL nAttrCol;
2019 : SCROW nAttrRow1, nAttrRow2;
2020 0 : const ScPatternAttr* pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
2021 0 : while ( pPattern )
2022 : {
2023 : const SfxPoolItem* pCondItem;
2024 0 : if ( pPattern->GetItemSet().GetItemState( ATTR_CONDITIONAL, true, &pCondItem )
2025 : == SFX_ITEM_SET )
2026 : {
2027 : // alle Formate durchgehen, damit die Zellen nicht einzeln
2028 : // angeschaut werden muessen
2029 :
2030 0 : const std::vector<sal_uInt32>& rCondFormatData = static_cast<const ScCondFormatItem*>(pCondItem)->GetCondFormatData();
2031 0 : ScStyleSheetPool* pStylePool = pDocument->GetStyleSheetPool();
2032 0 : if (mpCondFormatList && pStylePool && !rCondFormatData.empty())
2033 : {
2034 0 : for(std::vector<sal_uInt32>::const_iterator itr = rCondFormatData.begin(), itrEnd = rCondFormatData.end();
2035 : itr != itrEnd; ++itr)
2036 : {
2037 0 : const ScConditionalFormat* pFormat = mpCondFormatList->GetFormat(*itr);
2038 0 : if ( pFormat )
2039 : {
2040 0 : size_t nEntryCount = pFormat->size();
2041 0 : for (size_t nEntry=0; nEntry<nEntryCount; nEntry++)
2042 : {
2043 0 : const ScFormatEntry* pEntry = pFormat->GetEntry(nEntry);
2044 0 : if(pEntry->GetType() != condformat::CONDITION)
2045 0 : continue;
2046 :
2047 0 : OUString aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle();
2048 0 : if (!aStyleName.isEmpty())
2049 : {
2050 : SfxStyleSheetBase* pStyleSheet =
2051 0 : pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PARA );
2052 0 : if ( pStyleSheet )
2053 : {
2054 : FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
2055 : nCol, nAttrRow1, nAttrRow2,
2056 0 : nArrY, pPattern, &pStyleSheet->GetItemSet() );
2057 : // nArrY nicht veraendern
2058 : }
2059 : }
2060 0 : }
2061 : }
2062 : }
2063 : }
2064 : }
2065 :
2066 : nArrY = FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
2067 : nCol, nAttrRow1, nAttrRow2,
2068 0 : nArrY, pPattern, NULL );
2069 :
2070 0 : pPattern = aIter.GetNext( nAttrCol, nAttrRow1, nAttrRow2 );
2071 0 : }
2072 : }
2073 : }
2074 : }
2075 :
2076 0 : bool ScTable::HasBlockMatrixFragment( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const
2077 : {
2078 : using namespace sc;
2079 :
2080 0 : sal_uInt16 nEdges = 0;
2081 :
2082 0 : if ( nCol1 == nCol2 )
2083 : { // linke und rechte Spalte
2084 0 : const sal_uInt16 n = MatrixEdgeLeft | MatrixEdgeRight;
2085 0 : nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n );
2086 : // nicht (4 und 16) oder 1 oder 32
2087 0 : if (nEdges && (((nEdges & n) != n) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
2088 0 : return true; // linke oder rechte Kante fehlt oder offen
2089 : }
2090 : else
2091 : { // linke Spalte
2092 0 : nEdges = aCol[nCol1].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdgeLeft);
2093 : // nicht 4 oder 1 oder 32
2094 0 : if (nEdges && (((nEdges & MatrixEdgeLeft) != MatrixEdgeLeft) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
2095 0 : return true; // linke Kante fehlt oder offen
2096 : // rechte Spalte
2097 0 : nEdges = aCol[nCol2].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdgeRight);
2098 : // nicht 16 oder 1 oder 32
2099 0 : if (nEdges && (((nEdges & MatrixEdgeRight) != MatrixEdgeRight) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
2100 0 : return true; // rechte Kante fehlt oder offen
2101 : }
2102 :
2103 0 : if ( nRow1 == nRow2 )
2104 : { // obere und untere Zeile
2105 0 : bool bOpen = false;
2106 0 : const sal_uInt16 n = MatrixEdgeBottom | MatrixEdgeTop;
2107 0 : for ( SCCOL i=nCol1; i<=nCol2; i++)
2108 : {
2109 0 : nEdges = aCol[i].GetBlockMatrixEdges( nRow1, nRow1, n );
2110 0 : if ( nEdges )
2111 : {
2112 0 : if ( (nEdges & n) != n )
2113 0 : return true; // obere oder untere Kante fehlt
2114 0 : if (nEdges & MatrixEdgeLeft)
2115 0 : bOpen = true; // linke Kante oeffnet, weitersehen
2116 0 : else if ( !bOpen )
2117 0 : return true; // es gibt was, was nicht geoeffnet wurde
2118 0 : if (nEdges & MatrixEdgeRight)
2119 0 : bOpen = false; // rechte Kante schliesst
2120 : }
2121 : }
2122 0 : if ( bOpen )
2123 0 : return true; // es geht noch weiter
2124 : }
2125 : else
2126 : {
2127 : sal_uInt16 j, n;
2128 : SCROW nR;
2129 : // erst obere Zeile, dann untere Zeile
2130 0 : for ( j=0, nR=nRow1, n=8; j<2; j++, nR=nRow2, n=2 )
2131 : {
2132 0 : bool bOpen = false;
2133 0 : for ( SCCOL i=nCol1; i<=nCol2; i++)
2134 : {
2135 0 : nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n );
2136 0 : if ( nEdges )
2137 : {
2138 : // in oberere Zeile keine obere Kante bzw.
2139 : // in unterer Zeile keine untere Kante
2140 0 : if ( (nEdges & n) != n )
2141 0 : return true;
2142 0 : if (nEdges & MatrixEdgeLeft)
2143 0 : bOpen = true; // linke Kante oeffnet, weitersehen
2144 0 : else if ( !bOpen )
2145 0 : return true; // es gibt was, was nicht geoeffnet wurde
2146 0 : if (nEdges & MatrixEdgeRight)
2147 0 : bOpen = false; // rechte Kante schliesst
2148 : }
2149 : }
2150 0 : if ( bOpen )
2151 0 : return true; // es geht noch weiter
2152 : }
2153 : }
2154 0 : return false;
2155 : }
2156 :
2157 :
2158 0 : bool ScTable::HasSelectionMatrixFragment( const ScMarkData& rMark ) const
2159 : {
2160 0 : bool bFound = false;
2161 0 : for (SCCOL i=0; i<=MAXCOL && !bFound; i++)
2162 0 : bFound |= aCol[i].HasSelectionMatrixFragment(rMark);
2163 0 : return bFound;
2164 : }
2165 :
2166 :
2167 0 : bool ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2,
2168 : SCROW nRow2, bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
2169 : {
2170 0 : if ( !ValidColRow( nCol2, nRow2 ) )
2171 : {
2172 : OSL_FAIL("IsBlockEditable: invalid column or row");
2173 0 : if (pOnlyNotBecauseOfMatrix)
2174 0 : *pOnlyNotBecauseOfMatrix = false;
2175 0 : return false;
2176 : }
2177 :
2178 0 : bool bIsEditable = true;
2179 0 : if ( nLockCount )
2180 0 : bIsEditable = false;
2181 0 : else if ( IsProtected() && !pDocument->IsScenario(nTab) )
2182 : {
2183 0 : bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED );
2184 0 : if (!bIsEditable)
2185 : {
2186 : // An enhanced protection permission may override the attribute.
2187 0 : if (pTabProtection)
2188 0 : bIsEditable = pTabProtection->isBlockEditable( ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab));
2189 : }
2190 0 : if (bIsEditable)
2191 : {
2192 : // If Sheet is protected and cells are not protected then
2193 : // check the active scenario protect flag if this range is
2194 : // on the active scenario range. Note the 'copy back' must also
2195 : // be set to apply protection.
2196 0 : sal_uInt16 nScenTab = nTab+1;
2197 0 : while(pDocument->IsScenario(nScenTab))
2198 : {
2199 0 : ScRange aEditRange(nCol1, nRow1, nScenTab, nCol2, nRow2, nScenTab);
2200 0 : if(pDocument->IsActiveScenario(nScenTab) && pDocument->HasScenarioRange(nScenTab, aEditRange))
2201 : {
2202 : sal_uInt16 nFlags;
2203 0 : pDocument->GetScenarioFlags(nScenTab,nFlags);
2204 0 : bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY));
2205 0 : break;
2206 : }
2207 0 : nScenTab++;
2208 : }
2209 : }
2210 : }
2211 0 : else if (pDocument->IsScenario(nTab))
2212 : {
2213 : // Determine if the preceding sheet is protected
2214 0 : SCTAB nActualTab = nTab;
2215 0 : do
2216 : {
2217 0 : nActualTab--;
2218 : }
2219 0 : while(pDocument->IsScenario(nActualTab));
2220 :
2221 0 : if(pDocument->IsTabProtected(nActualTab))
2222 : {
2223 0 : ScRange aEditRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab);
2224 0 : if(pDocument->HasScenarioRange(nTab, aEditRange))
2225 : {
2226 : sal_uInt16 nFlags;
2227 0 : pDocument->GetScenarioFlags(nTab,nFlags);
2228 0 : bIsEditable = !(nFlags & SC_SCENARIO_PROTECT);
2229 : }
2230 : }
2231 : }
2232 0 : if ( bIsEditable )
2233 : {
2234 0 : if ( HasBlockMatrixFragment( nCol1, nRow1, nCol2, nRow2 ) )
2235 : {
2236 0 : bIsEditable = false;
2237 0 : if ( pOnlyNotBecauseOfMatrix )
2238 0 : *pOnlyNotBecauseOfMatrix = true;
2239 : }
2240 0 : else if ( pOnlyNotBecauseOfMatrix )
2241 0 : *pOnlyNotBecauseOfMatrix = false;
2242 : }
2243 0 : else if ( pOnlyNotBecauseOfMatrix )
2244 0 : *pOnlyNotBecauseOfMatrix = false;
2245 0 : return bIsEditable;
2246 : }
2247 :
2248 :
2249 0 : bool ScTable::IsSelectionEditable( const ScMarkData& rMark,
2250 : bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
2251 : {
2252 0 : bool bIsEditable = true;
2253 0 : if ( nLockCount )
2254 0 : bIsEditable = false;
2255 0 : else if ( IsProtected() && !pDocument->IsScenario(nTab) )
2256 : {
2257 0 : ScRangeList aRanges;
2258 0 : rMark.FillRangeListWithMarks( &aRanges, false );
2259 0 : bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED );
2260 0 : if (!bIsEditable)
2261 : {
2262 : // An enhanced protection permission may override the attribute.
2263 0 : if (pTabProtection)
2264 0 : bIsEditable = pTabProtection->isSelectionEditable( aRanges);
2265 : }
2266 0 : if (bIsEditable)
2267 : {
2268 : // If Sheet is protected and cells are not protected then
2269 : // check the active scenario protect flag if this area is
2270 : // in the active scenario range.
2271 0 : SCTAB nScenTab = nTab+1;
2272 0 : while(pDocument->IsScenario(nScenTab) && bIsEditable)
2273 : {
2274 0 : if(pDocument->IsActiveScenario(nScenTab))
2275 : {
2276 0 : for (size_t i=0, nRange = aRanges.size(); (i < nRange) && bIsEditable; i++ )
2277 : {
2278 0 : ScRange aRange = *aRanges[ i ];
2279 0 : if(pDocument->HasScenarioRange(nScenTab, aRange))
2280 : {
2281 : sal_uInt16 nFlags;
2282 0 : pDocument->GetScenarioFlags(nScenTab,nFlags);
2283 0 : bIsEditable = !((nFlags & SC_SCENARIO_PROTECT) && (nFlags & SC_SCENARIO_TWOWAY));
2284 : }
2285 : }
2286 : }
2287 0 : nScenTab++;
2288 : }
2289 0 : }
2290 : }
2291 0 : else if (pDocument->IsScenario(nTab))
2292 : {
2293 : // Determine if the preceding sheet is protected
2294 0 : SCTAB nActualTab = nTab;
2295 0 : do
2296 : {
2297 0 : nActualTab--;
2298 : }
2299 0 : while(pDocument->IsScenario(nActualTab));
2300 :
2301 0 : if(pDocument->IsTabProtected(nActualTab))
2302 : {
2303 0 : ScRangeList aRanges;
2304 0 : rMark.FillRangeListWithMarks( &aRanges, false );
2305 0 : for (size_t i = 0, nRange = aRanges.size(); (i < nRange) && bIsEditable; i++)
2306 : {
2307 0 : ScRange aRange = *aRanges[ i ];
2308 0 : if(pDocument->HasScenarioRange(nTab, aRange))
2309 : {
2310 : sal_uInt16 nFlags;
2311 0 : pDocument->GetScenarioFlags(nTab,nFlags);
2312 0 : bIsEditable = !(nFlags & SC_SCENARIO_PROTECT);
2313 : }
2314 0 : }
2315 : }
2316 : }
2317 0 : if ( bIsEditable )
2318 : {
2319 0 : if ( HasSelectionMatrixFragment( rMark ) )
2320 : {
2321 0 : bIsEditable = false;
2322 0 : if ( pOnlyNotBecauseOfMatrix )
2323 0 : *pOnlyNotBecauseOfMatrix = true;
2324 : }
2325 0 : else if ( pOnlyNotBecauseOfMatrix )
2326 0 : *pOnlyNotBecauseOfMatrix = false;
2327 : }
2328 0 : else if ( pOnlyNotBecauseOfMatrix )
2329 0 : *pOnlyNotBecauseOfMatrix = false;
2330 0 : return bIsEditable;
2331 : }
2332 :
2333 0 : void ScTable::LockTable()
2334 : {
2335 0 : ++nLockCount;
2336 0 : }
2337 :
2338 :
2339 0 : void ScTable::UnlockTable()
2340 : {
2341 0 : if (nLockCount)
2342 0 : --nLockCount;
2343 : else
2344 : {
2345 : OSL_FAIL("UnlockTable without LockTable");
2346 : }
2347 0 : }
2348 :
2349 :
2350 0 : void ScTable::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
2351 : {
2352 0 : for (SCCOL i=0; i<=MAXCOL; i++)
2353 0 : aCol[i].MergeSelectionPattern( rState, rMark, bDeep );
2354 0 : }
2355 :
2356 :
2357 0 : void ScTable::MergePatternArea( ScMergePatternState& rState, SCCOL nCol1, SCROW nRow1,
2358 : SCCOL nCol2, SCROW nRow2, bool bDeep ) const
2359 : {
2360 0 : for (SCCOL i=nCol1; i<=nCol2; i++)
2361 0 : aCol[i].MergePatternArea( rState, nRow1, nRow2, bDeep );
2362 0 : }
2363 :
2364 :
2365 0 : void ScTable::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner, ScLineFlags& rFlags,
2366 : SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const
2367 : {
2368 0 : if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2369 : {
2370 0 : PutInOrder(nStartCol, nEndCol);
2371 0 : PutInOrder(nStartRow, nEndRow);
2372 0 : for (SCCOL i=nStartCol; i<=nEndCol; i++)
2373 0 : aCol[i].MergeBlockFrame( pLineOuter, pLineInner, rFlags,
2374 0 : nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
2375 : }
2376 0 : }
2377 :
2378 :
2379 0 : void ScTable::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
2380 : SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
2381 : {
2382 0 : if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2383 : {
2384 0 : PutInOrder(nStartCol, nEndCol);
2385 0 : PutInOrder(nStartRow, nEndRow);
2386 0 : for (SCCOL i=nStartCol; i<=nEndCol; i++)
2387 0 : aCol[i].ApplyBlockFrame( pLineOuter, pLineInner,
2388 0 : nStartRow, nEndRow, (i==nStartCol), nEndCol-i );
2389 : }
2390 0 : }
2391 :
2392 :
2393 0 : void ScTable::ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr )
2394 : {
2395 0 : if (ValidColRow(nCol,nRow))
2396 0 : aCol[nCol].ApplyPattern( nRow, rAttr );
2397 0 : }
2398 :
2399 :
2400 0 : void ScTable::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2401 : const ScPatternAttr& rAttr, ScEditDataArray* pDataArray )
2402 : {
2403 0 : if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2404 : {
2405 0 : PutInOrder(nStartCol, nEndCol);
2406 0 : PutInOrder(nStartRow, nEndRow);
2407 0 : for (SCCOL i = nStartCol; i <= nEndCol; i++)
2408 0 : aCol[i].ApplyPatternArea(nStartRow, nEndRow, rAttr, pDataArray);
2409 : }
2410 0 : }
2411 :
2412 0 : bool ScTable::SetAttrEntries(SCCOL nCol, ScAttrEntry* pData, SCSIZE nSize)
2413 : {
2414 0 : if (!ValidCol(nCol))
2415 0 : return false;
2416 :
2417 0 : return aCol[nCol].SetAttrEntries(pData, nSize);
2418 : }
2419 :
2420 0 : void ScTable::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
2421 : const ScPatternAttr& rPattern, short nNewType )
2422 : {
2423 0 : SCCOL nEndCol = rRange.aEnd.Col();
2424 0 : for ( SCCOL nCol = rRange.aStart.Col(); nCol <= nEndCol; nCol++ )
2425 : {
2426 0 : aCol[nCol].ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
2427 : }
2428 0 : }
2429 :
2430 0 : void ScTable::AddCondFormatData( const ScRangeList& rRange, sal_uInt32 nIndex )
2431 : {
2432 0 : size_t n = rRange.size();
2433 0 : for(size_t i = 0; i < n; ++i)
2434 : {
2435 0 : const ScRange* pRange = rRange[i];
2436 0 : SCCOL nColStart = pRange->aStart.Col();
2437 0 : SCCOL nColEnd = pRange->aEnd.Col();
2438 0 : SCROW nRowStart = pRange->aStart.Row();
2439 0 : SCROW nRowEnd = pRange->aEnd.Row();
2440 0 : for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
2441 : {
2442 0 : aCol[nCol].AddCondFormat(nRowStart, nRowEnd, nIndex);
2443 : }
2444 : }
2445 0 : }
2446 :
2447 0 : void ScTable::RemoveCondFormatData( const ScRangeList& rRange, sal_uInt32 nIndex )
2448 : {
2449 0 : size_t n = rRange.size();
2450 0 : for(size_t i = 0; i < n; ++i)
2451 : {
2452 0 : const ScRange* pRange = rRange[i];
2453 0 : SCCOL nColStart = pRange->aStart.Col();
2454 0 : SCCOL nColEnd = pRange->aEnd.Col();
2455 0 : SCROW nRowStart = pRange->aStart.Row();
2456 0 : SCROW nRowEnd = pRange->aEnd.Row();
2457 0 : for(SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
2458 : {
2459 0 : aCol[nCol].RemoveCondFormat(nRowStart, nRowEnd, nIndex);
2460 : }
2461 : }
2462 0 : }
2463 :
2464 0 : void ScTable::ApplyStyle( SCCOL nCol, SCROW nRow, const ScStyleSheet& rStyle )
2465 : {
2466 0 : if (ValidColRow(nCol,nRow))
2467 0 : aCol[nCol].ApplyStyle( nRow, rStyle );
2468 0 : }
2469 :
2470 :
2471 0 : void ScTable::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScStyleSheet& rStyle )
2472 : {
2473 0 : if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2474 : {
2475 0 : PutInOrder(nStartCol, nEndCol);
2476 0 : PutInOrder(nStartRow, nEndRow);
2477 0 : for (SCCOL i = nStartCol; i <= nEndCol; i++)
2478 0 : aCol[i].ApplyStyleArea(nStartRow, nEndRow, rStyle);
2479 : }
2480 0 : }
2481 :
2482 :
2483 0 : void ScTable::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
2484 : {
2485 0 : for (SCCOL i=0; i<=MAXCOL; i++)
2486 0 : aCol[i].ApplySelectionStyle( rStyle, rMark );
2487 0 : }
2488 :
2489 :
2490 0 : void ScTable::ApplySelectionLineStyle( const ScMarkData& rMark,
2491 : const ::editeng::SvxBorderLine* pLine, bool bColorOnly )
2492 : {
2493 0 : if ( bColorOnly && !pLine )
2494 0 : return;
2495 :
2496 0 : for (SCCOL i=0; i<=MAXCOL; i++)
2497 0 : aCol[i].ApplySelectionLineStyle( rMark, pLine, bColorOnly );
2498 : }
2499 :
2500 :
2501 0 : const ScStyleSheet* ScTable::GetStyle( SCCOL nCol, SCROW nRow ) const
2502 : {
2503 0 : if (ValidColRow(nCol, nRow))
2504 0 : return aCol[nCol].GetStyle(nRow);
2505 : else
2506 0 : return NULL;
2507 : }
2508 :
2509 :
2510 0 : const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
2511 : {
2512 0 : rFound = false;
2513 :
2514 0 : bool bEqual = true;
2515 : bool bColFound;
2516 :
2517 0 : const ScStyleSheet* pStyle = NULL;
2518 : const ScStyleSheet* pNewStyle;
2519 :
2520 0 : for (SCCOL i=0; i<=MAXCOL && bEqual; i++)
2521 0 : if (rMark.HasMultiMarks(i))
2522 : {
2523 0 : pNewStyle = aCol[i].GetSelectionStyle( rMark, bColFound );
2524 0 : if (bColFound)
2525 : {
2526 0 : rFound = true;
2527 0 : if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2528 0 : bEqual = false; // unterschiedliche
2529 0 : pStyle = pNewStyle;
2530 : }
2531 : }
2532 :
2533 0 : return bEqual ? pStyle : NULL;
2534 : }
2535 :
2536 :
2537 0 : const ScStyleSheet* ScTable::GetAreaStyle( bool& rFound, SCCOL nCol1, SCROW nRow1,
2538 : SCCOL nCol2, SCROW nRow2 ) const
2539 : {
2540 0 : rFound = false;
2541 :
2542 0 : bool bEqual = true;
2543 : bool bColFound;
2544 :
2545 0 : const ScStyleSheet* pStyle = NULL;
2546 : const ScStyleSheet* pNewStyle;
2547 :
2548 0 : for (SCCOL i=nCol1; i<=nCol2 && bEqual; i++)
2549 : {
2550 0 : pNewStyle = aCol[i].GetAreaStyle(bColFound, nRow1, nRow2);
2551 0 : if (bColFound)
2552 : {
2553 0 : rFound = true;
2554 0 : if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
2555 0 : bEqual = false; // unterschiedliche
2556 0 : pStyle = pNewStyle;
2557 : }
2558 : }
2559 :
2560 0 : return bEqual ? pStyle : NULL;
2561 : }
2562 :
2563 :
2564 0 : bool ScTable::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
2565 : {
2566 0 : bool bIsUsed = false;
2567 :
2568 0 : for ( SCCOL i=0; i<=MAXCOL; i++ )
2569 : {
2570 0 : if ( aCol[i].IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
2571 : {
2572 0 : if ( !bGatherAllStyles )
2573 0 : return true;
2574 0 : bIsUsed = true;
2575 : }
2576 : }
2577 :
2578 0 : return bIsUsed;
2579 : }
2580 :
2581 :
2582 0 : void ScTable::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, bool bRemoved,
2583 : OutputDevice* pDev,
2584 : double nPPTX, double nPPTY,
2585 : const Fraction& rZoomX, const Fraction& rZoomY )
2586 : {
2587 0 : ScFlatBoolRowSegments aUsedRows;
2588 0 : for (SCCOL i = 0; i <= MAXCOL; ++i)
2589 0 : aCol[i].FindStyleSheet(pStyleSheet, aUsedRows, bRemoved);
2590 :
2591 0 : sc::RowHeightContext aCxt(nPPTX, nPPTY, rZoomX, rZoomY, pDev);
2592 0 : SCROW nRow = 0;
2593 0 : while (nRow <= MAXROW)
2594 : {
2595 : ScFlatBoolRowSegments::RangeData aData;
2596 0 : if (!aUsedRows.getRangeData(nRow, aData))
2597 : // search failed!
2598 0 : return;
2599 :
2600 0 : SCROW nEndRow = aData.mnRow2;
2601 0 : if (aData.mbValue)
2602 0 : SetOptimalHeight(aCxt, nRow, nEndRow);
2603 :
2604 0 : nRow = nEndRow + 1;
2605 0 : }
2606 : }
2607 :
2608 :
2609 0 : bool ScTable::ApplyFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2610 : sal_Int16 nFlags )
2611 : {
2612 0 : bool bChanged = false;
2613 0 : if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2614 0 : for (SCCOL i = nStartCol; i <= nEndCol; i++)
2615 0 : bChanged |= aCol[i].ApplyFlags(nStartRow, nEndRow, nFlags);
2616 0 : return bChanged;
2617 : }
2618 :
2619 :
2620 0 : bool ScTable::RemoveFlags( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
2621 : sal_Int16 nFlags )
2622 : {
2623 0 : bool bChanged = false;
2624 0 : if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
2625 0 : for (SCCOL i = nStartCol; i <= nEndCol; i++)
2626 0 : bChanged |= aCol[i].RemoveFlags(nStartRow, nEndRow, nFlags);
2627 0 : return bChanged;
2628 : }
2629 :
2630 :
2631 0 : void ScTable::SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, bool bPutToPool )
2632 : {
2633 0 : if (ValidColRow(nCol,nRow))
2634 0 : aCol[nCol].SetPattern( nRow, rAttr, bPutToPool );
2635 0 : }
2636 :
2637 :
2638 0 : void ScTable::ApplyAttr( SCCOL nCol, SCROW nRow, const SfxPoolItem& rAttr )
2639 : {
2640 0 : if (ValidColRow(nCol,nRow))
2641 0 : aCol[nCol].ApplyAttr( nRow, rAttr );
2642 0 : }
2643 :
2644 :
2645 0 : void ScTable::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark,
2646 : ScEditDataArray* pDataArray )
2647 : {
2648 0 : for (SCCOL i=0; i<=MAXCOL; i++)
2649 0 : aCol[i].ApplySelectionCache( pCache, rMark, pDataArray );
2650 0 : }
2651 :
2652 :
2653 0 : void ScTable::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
2654 : {
2655 0 : for (SCCOL i=0; i<=MAXCOL; i++)
2656 0 : aCol[i].ChangeSelectionIndent( bIncrement, rMark );
2657 0 : }
2658 :
2659 :
2660 0 : void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
2661 : {
2662 0 : for (SCCOL i=0; i<=MAXCOL; i++)
2663 0 : aCol[i].ClearSelectionItems( pWhich, rMark );
2664 0 : }
2665 :
2666 :
2667 : // Spaltenbreiten / Zeilenhoehen
2668 :
2669 0 : void ScTable::SetColWidth( SCCOL nCol, sal_uInt16 nNewWidth )
2670 : {
2671 0 : if (ValidCol(nCol) && pColWidth)
2672 : {
2673 0 : if (!nNewWidth)
2674 : {
2675 0 : nNewWidth = STD_COL_WIDTH;
2676 : }
2677 :
2678 0 : if ( nNewWidth != pColWidth[nCol] )
2679 : {
2680 0 : pColWidth[nCol] = nNewWidth;
2681 0 : InvalidatePageBreaks();
2682 : }
2683 : }
2684 : else
2685 : {
2686 : OSL_FAIL("Invalid column number or no widths");
2687 : }
2688 0 : }
2689 :
2690 0 : void ScTable::SetColWidthOnly( SCCOL nCol, sal_uInt16 nNewWidth )
2691 : {
2692 0 : if (!ValidCol(nCol) || !pColWidth)
2693 0 : return;
2694 :
2695 0 : if (!nNewWidth)
2696 0 : nNewWidth = STD_COL_WIDTH;
2697 :
2698 0 : if (nNewWidth != pColWidth[nCol])
2699 0 : pColWidth[nCol] = nNewWidth;
2700 : }
2701 :
2702 0 : void ScTable::SetRowHeight( SCROW nRow, sal_uInt16 nNewHeight )
2703 : {
2704 0 : if (ValidRow(nRow) && mpRowHeights)
2705 : {
2706 0 : if (!nNewHeight)
2707 : {
2708 : OSL_FAIL("SetRowHeight: Row height zero");
2709 0 : nNewHeight = ScGlobal::nStdRowHeight;
2710 : }
2711 :
2712 0 : sal_uInt16 nOldHeight = mpRowHeights->getValue(nRow);
2713 0 : if ( nNewHeight != nOldHeight )
2714 : {
2715 0 : mpRowHeights->setValue(nRow, nRow, nNewHeight);
2716 0 : InvalidatePageBreaks();
2717 : }
2718 : }
2719 : else
2720 : {
2721 : OSL_FAIL("Invalid row number or no heights");
2722 : }
2723 0 : }
2724 :
2725 : namespace {
2726 :
2727 : /**
2728 : * Check if the new pixel size is different from the old size between
2729 : * specified ranges.
2730 : */
2731 0 : bool lcl_pixelSizeChanged(
2732 : ScFlatUInt16RowSegments& rRowHeights, SCROW nStartRow, SCROW nEndRow,
2733 : sal_uInt16 nNewHeight, double nPPTY)
2734 : {
2735 0 : long nNewPix = static_cast<long>(nNewHeight * nPPTY);
2736 :
2737 0 : ScFlatUInt16RowSegments::ForwardIterator aFwdIter(rRowHeights);
2738 0 : for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
2739 : {
2740 : sal_uInt16 nHeight;
2741 0 : if (!aFwdIter.getValue(nRow, nHeight))
2742 0 : break;
2743 :
2744 0 : if (nHeight != nNewHeight)
2745 : {
2746 0 : bool bChanged = (nNewPix != static_cast<long>(nHeight * nPPTY));
2747 0 : if (bChanged)
2748 0 : return true;
2749 : }
2750 :
2751 : // Skip ahead to the last position of the current range.
2752 0 : nRow = aFwdIter.getLastPos();
2753 : }
2754 0 : return false;
2755 : }
2756 :
2757 : }
2758 :
2759 0 : bool ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight,
2760 : double /* nPPTX */, double nPPTY )
2761 : {
2762 0 : bool bChanged = false;
2763 0 : if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2764 : {
2765 0 : if (!nNewHeight)
2766 : {
2767 : OSL_FAIL("SetRowHeight: Row height zero");
2768 0 : nNewHeight = ScGlobal::nStdRowHeight;
2769 : }
2770 :
2771 0 : bool bSingle = false; // true = process every row for its own
2772 0 : ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
2773 0 : if (pDrawLayer)
2774 0 : if (pDrawLayer->HasObjectsInRows( nTab, nStartRow, nEndRow ))
2775 0 : bSingle = true;
2776 :
2777 0 : if (bSingle)
2778 : {
2779 : ScFlatUInt16RowSegments::RangeData aData;
2780 0 : mpRowHeights->getRangeData(nStartRow, aData);
2781 0 : if (nNewHeight == aData.mnValue && nEndRow <= aData.mnRow2)
2782 0 : bSingle = false; // no difference in this range
2783 : }
2784 0 : if (bSingle)
2785 : {
2786 0 : if (nEndRow-nStartRow < 20)
2787 : {
2788 0 : if (!bChanged)
2789 0 : bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2790 :
2791 0 : mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2792 : }
2793 : else
2794 : {
2795 0 : SCROW nMid = (nStartRow+nEndRow) / 2;
2796 0 : if (SetRowHeightRange( nStartRow, nMid, nNewHeight, 1.0, 1.0 ))
2797 0 : bChanged = true;
2798 0 : if (SetRowHeightRange( nMid+1, nEndRow, nNewHeight, 1.0, 1.0 ))
2799 0 : bChanged = true;
2800 : }
2801 : }
2802 : else
2803 : {
2804 0 : if (!bChanged)
2805 0 : bChanged = lcl_pixelSizeChanged(*mpRowHeights, nStartRow, nEndRow, nNewHeight, nPPTY);
2806 :
2807 0 : mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2808 : }
2809 :
2810 0 : if (bChanged)
2811 0 : InvalidatePageBreaks();
2812 : }
2813 : else
2814 : {
2815 : OSL_FAIL("Invalid row number or no heights");
2816 : }
2817 :
2818 0 : return bChanged;
2819 : }
2820 :
2821 0 : void ScTable::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nNewHeight )
2822 : {
2823 0 : if (!ValidRow(nStartRow) || !ValidRow(nEndRow) || !mpRowHeights)
2824 0 : return;
2825 :
2826 0 : if (!nNewHeight)
2827 0 : nNewHeight = ScGlobal::nStdRowHeight;
2828 :
2829 0 : mpRowHeights->setValue(nStartRow, nEndRow, nNewHeight);
2830 : }
2831 :
2832 0 : void ScTable::SetManualHeight( SCROW nStartRow, SCROW nEndRow, bool bManual )
2833 : {
2834 0 : if (ValidRow(nStartRow) && ValidRow(nEndRow) && pRowFlags)
2835 : {
2836 0 : if (bManual)
2837 0 : pRowFlags->OrValue( nStartRow, nEndRow, CR_MANUALSIZE);
2838 : else
2839 0 : pRowFlags->AndValue( nStartRow, nEndRow, sal::static_int_cast<sal_uInt8>(~CR_MANUALSIZE));
2840 : }
2841 : else
2842 : {
2843 : OSL_FAIL("Invalid row number or no column flags");
2844 : }
2845 0 : }
2846 :
2847 :
2848 0 : sal_uInt16 ScTable::GetColWidth( SCCOL nCol, bool bHiddenAsZero ) const
2849 : {
2850 : OSL_ENSURE(ValidCol(nCol),"wrong column number");
2851 :
2852 0 : if (ValidCol(nCol) && pColFlags && pColWidth)
2853 : {
2854 0 : if (bHiddenAsZero && ColHidden(nCol))
2855 0 : return 0;
2856 : else
2857 0 : return pColWidth[nCol];
2858 : }
2859 : else
2860 0 : return (sal_uInt16) STD_COL_WIDTH;
2861 : }
2862 :
2863 :
2864 0 : sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const // immer die eingestellte
2865 : {
2866 : OSL_ENSURE(ValidCol(nCol),"wrong column number");
2867 :
2868 0 : if (ValidCol(nCol) && pColWidth)
2869 0 : return pColWidth[nCol];
2870 : else
2871 0 : return (sal_uInt16) STD_COL_WIDTH;
2872 : }
2873 :
2874 :
2875 0 : sal_uInt16 ScTable::GetCommonWidth( SCCOL nEndCol ) const
2876 : {
2877 : // get the width that is used in the largest continuous column range (up to nEndCol)
2878 :
2879 0 : if ( !ValidCol(nEndCol) )
2880 : {
2881 : OSL_FAIL("wrong column");
2882 0 : nEndCol = MAXCOL;
2883 : }
2884 :
2885 0 : sal_uInt16 nMaxWidth = 0;
2886 0 : sal_uInt16 nMaxCount = 0;
2887 0 : SCCOL nRangeStart = 0;
2888 0 : while ( nRangeStart <= nEndCol )
2889 : {
2890 : // skip hidden columns
2891 0 : while ( nRangeStart <= nEndCol && ColHidden(nRangeStart) )
2892 0 : ++nRangeStart;
2893 0 : if ( nRangeStart <= nEndCol )
2894 : {
2895 0 : sal_uInt16 nThisCount = 0;
2896 0 : sal_uInt16 nThisWidth = pColWidth[nRangeStart];
2897 0 : SCCOL nRangeEnd = nRangeStart;
2898 0 : while ( nRangeEnd <= nEndCol && pColWidth[nRangeEnd] == nThisWidth )
2899 : {
2900 0 : ++nThisCount;
2901 0 : ++nRangeEnd;
2902 :
2903 : // skip hidden columns
2904 0 : while ( nRangeEnd <= nEndCol && ColHidden(nRangeEnd) )
2905 0 : ++nRangeEnd;
2906 : }
2907 :
2908 0 : if ( nThisCount > nMaxCount )
2909 : {
2910 0 : nMaxCount = nThisCount;
2911 0 : nMaxWidth = nThisWidth;
2912 : }
2913 :
2914 0 : nRangeStart = nRangeEnd; // next range
2915 : }
2916 : }
2917 :
2918 0 : return nMaxWidth;
2919 : }
2920 :
2921 :
2922 0 : sal_uInt16 ScTable::GetRowHeight( SCROW nRow, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
2923 : {
2924 : OSL_ENSURE(ValidRow(nRow),"Invalid row number");
2925 :
2926 0 : if (ValidRow(nRow) && mpRowHeights)
2927 : {
2928 0 : if (bHiddenAsZero && RowHidden( nRow, pStartRow, pEndRow))
2929 0 : return 0;
2930 : else
2931 : {
2932 : ScFlatUInt16RowSegments::RangeData aData;
2933 0 : if (!mpRowHeights->getRangeData(nRow, aData))
2934 : {
2935 0 : if (pStartRow)
2936 0 : *pStartRow = nRow;
2937 0 : if (pEndRow)
2938 0 : *pEndRow = nRow;
2939 : // TODO: What should we return in case the search fails?
2940 0 : return 0;
2941 : }
2942 :
2943 : // If bHiddenAsZero, pStartRow and pEndRow were initialized to
2944 : // boundaries of a non-hidden segment. Assume that the previous and
2945 : // next segment are hidden then and limit the current height
2946 : // segment.
2947 0 : if (pStartRow)
2948 0 : *pStartRow = (bHiddenAsZero ? std::max( *pStartRow, aData.mnRow1) : aData.mnRow1);
2949 0 : if (pEndRow)
2950 0 : *pEndRow = (bHiddenAsZero ? std::min( *pEndRow, aData.mnRow2) : aData.mnRow2);
2951 0 : return aData.mnValue;
2952 : }
2953 : }
2954 : else
2955 : {
2956 0 : if (pStartRow)
2957 0 : *pStartRow = nRow;
2958 0 : if (pEndRow)
2959 0 : *pEndRow = nRow;
2960 0 : return (sal_uInt16) ScGlobal::nStdRowHeight;
2961 : }
2962 : }
2963 :
2964 :
2965 0 : sal_uLong ScTable::GetRowHeight( SCROW nStartRow, SCROW nEndRow, bool bHiddenAsZero ) const
2966 : {
2967 : OSL_ENSURE(ValidRow(nStartRow) && ValidRow(nEndRow),"wrong row number");
2968 :
2969 0 : if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2970 : {
2971 0 : sal_uLong nHeight = 0;
2972 0 : SCROW nRow = nStartRow;
2973 0 : while (nRow <= nEndRow)
2974 : {
2975 0 : SCROW nLastRow = -1;
2976 0 : if (!( ( RowHidden(nRow, NULL, &nLastRow) ) && bHiddenAsZero ) )
2977 : {
2978 0 : if (nLastRow > nEndRow)
2979 0 : nLastRow = nEndRow;
2980 0 : nHeight += mpRowHeights->getSumValue(nRow, nLastRow);
2981 : }
2982 0 : nRow = nLastRow + 1;
2983 : }
2984 0 : return nHeight;
2985 : }
2986 : else
2987 0 : return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight);
2988 : }
2989 :
2990 :
2991 0 : sal_uLong ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fScale ) const
2992 : {
2993 : OSL_ENSURE(ValidRow(nStartRow) && ValidRow(nEndRow),"wrong row number");
2994 :
2995 0 : if (ValidRow(nStartRow) && ValidRow(nEndRow) && mpRowHeights)
2996 : {
2997 0 : sal_uLong nHeight = 0;
2998 0 : SCROW nRow = nStartRow;
2999 0 : while (nRow <= nEndRow)
3000 : {
3001 0 : SCROW nLastRow = -1;
3002 0 : if (!RowHidden(nRow, NULL, &nLastRow))
3003 : {
3004 0 : if (nLastRow > nEndRow)
3005 0 : nLastRow = nEndRow;
3006 :
3007 : // #i117315# can't use getSumValue, because individual values must be rounded
3008 0 : while (nRow <= nLastRow)
3009 : {
3010 : ScFlatUInt16RowSegments::RangeData aData;
3011 0 : if (!mpRowHeights->getRangeData(nRow, aData))
3012 0 : return nHeight; // shouldn't happen
3013 :
3014 0 : SCROW nSegmentEnd = std::min( nLastRow, aData.mnRow2 );
3015 :
3016 : // round-down a single height value, multiply resulting (pixel) values
3017 0 : sal_uLong nOneHeight = static_cast<sal_uLong>( aData.mnValue * fScale );
3018 0 : nHeight += nOneHeight * ( nSegmentEnd + 1 - nRow );
3019 :
3020 0 : nRow = nSegmentEnd + 1;
3021 : }
3022 : }
3023 0 : nRow = nLastRow + 1;
3024 : }
3025 0 : return nHeight;
3026 : }
3027 : else
3028 0 : return (sal_uLong) ((nEndRow - nStartRow + 1) * ScGlobal::nStdRowHeight * fScale);
3029 : }
3030 :
3031 :
3032 0 : sal_uInt16 ScTable::GetOriginalHeight( SCROW nRow ) const // non-0 even if hidden
3033 : {
3034 : OSL_ENSURE(ValidRow(nRow),"wrong row number");
3035 :
3036 0 : if (ValidRow(nRow) && mpRowHeights)
3037 0 : return mpRowHeights->getValue(nRow);
3038 : else
3039 0 : return (sal_uInt16) ScGlobal::nStdRowHeight;
3040 : }
3041 :
3042 :
3043 : // Spalten-/Zeilen-Flags
3044 :
3045 :
3046 0 : SCROW ScTable::GetHiddenRowCount( SCROW nRow ) const
3047 : {
3048 0 : if (!ValidRow(nRow))
3049 0 : return 0;
3050 :
3051 0 : SCROW nLastRow = -1;
3052 0 : if (!RowHidden(nRow, NULL, &nLastRow) || !ValidRow(nLastRow))
3053 0 : return 0;
3054 :
3055 0 : return nLastRow - nRow + 1;
3056 : }
3057 :
3058 :
3059 : //! ShowRows / DBShowRows zusammenfassen
3060 :
3061 0 : void ScTable::ShowCol(SCCOL nCol, bool bShow)
3062 : {
3063 0 : if (ValidCol(nCol))
3064 : {
3065 0 : bool bWasVis = !ColHidden(nCol);
3066 0 : if (bWasVis != bShow)
3067 : {
3068 0 : SetColHidden(nCol, nCol, !bShow);
3069 :
3070 0 : ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3071 0 : if ( pCharts )
3072 0 : pCharts->SetRangeDirty(ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ));
3073 : }
3074 : }
3075 : else
3076 : {
3077 : OSL_FAIL("Invalid column number or no flags");
3078 : }
3079 0 : }
3080 :
3081 :
3082 0 : void ScTable::ShowRow(SCROW nRow, bool bShow)
3083 : {
3084 0 : if (ValidRow(nRow) && pRowFlags)
3085 : {
3086 0 : bool bWasVis = !RowHidden(nRow);
3087 0 : if (bWasVis != bShow)
3088 : {
3089 0 : SetRowHidden(nRow, nRow, !bShow);
3090 0 : if (bShow)
3091 0 : SetRowFiltered(nRow, nRow, false);
3092 0 : ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3093 0 : if ( pCharts )
3094 0 : pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
3095 :
3096 0 : InvalidatePageBreaks();
3097 : }
3098 : }
3099 : else
3100 : {
3101 : OSL_FAIL("Invalid row number or no flags");
3102 : }
3103 0 : }
3104 :
3105 :
3106 0 : void ScTable::DBShowRow(SCROW nRow, bool bShow)
3107 : {
3108 0 : if (ValidRow(nRow) && pRowFlags)
3109 : {
3110 : // Filter-Flag immer setzen, auch wenn Hidden unveraendert
3111 0 : bool bChanged = SetRowHidden(nRow, nRow, !bShow);
3112 0 : SetRowFiltered(nRow, nRow, !bShow);
3113 :
3114 0 : if (bChanged)
3115 : {
3116 0 : ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3117 0 : if ( pCharts )
3118 0 : pCharts->SetRangeDirty(ScRange( 0, nRow, nTab, MAXCOL, nRow, nTab ));
3119 :
3120 0 : if (pOutlineTable)
3121 0 : UpdateOutlineRow( nRow, nRow, bShow );
3122 :
3123 0 : InvalidatePageBreaks();
3124 : }
3125 : }
3126 : else
3127 : {
3128 : OSL_FAIL("Invalid row number or no flags");
3129 : }
3130 0 : }
3131 :
3132 :
3133 0 : void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
3134 : {
3135 0 : SCROW nStartRow = nRow1;
3136 0 : while (nStartRow <= nRow2)
3137 : {
3138 0 : SCROW nEndRow = -1;
3139 0 : bool bWasVis = !RowHiddenLeaf(nStartRow, NULL, &nEndRow);
3140 0 : if (nEndRow > nRow2)
3141 0 : nEndRow = nRow2;
3142 :
3143 0 : bool bChanged = ( bWasVis != bShow );
3144 :
3145 0 : SetRowHidden(nStartRow, nEndRow, !bShow);
3146 0 : SetRowFiltered(nStartRow, nEndRow, !bShow);
3147 :
3148 0 : if ( bChanged )
3149 : {
3150 0 : ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3151 0 : if ( pCharts )
3152 0 : pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
3153 : }
3154 :
3155 0 : nStartRow = nEndRow + 1;
3156 : }
3157 :
3158 : // #i12341# For Show/Hide rows, the outlines are updated separately from the outside.
3159 : // For filtering, the changes aren't visible to the caller, so UpdateOutlineRow has
3160 : // to be done here.
3161 0 : if (pOutlineTable)
3162 0 : UpdateOutlineRow( nRow1, nRow2, bShow );
3163 0 : }
3164 :
3165 :
3166 0 : void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow)
3167 : {
3168 0 : SCROW nStartRow = nRow1;
3169 :
3170 : // #i116164# if there are no drawing objects within the row range, a single HeightChanged call is enough
3171 0 : ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
3172 0 : bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, nRow1, nRow2 );
3173 :
3174 0 : while (nStartRow <= nRow2)
3175 : {
3176 0 : SCROW nEndRow = -1;
3177 0 : bool bWasVis = !RowHiddenLeaf(nStartRow, NULL, &nEndRow);
3178 0 : if (nEndRow > nRow2)
3179 0 : nEndRow = nRow2;
3180 :
3181 0 : bool bChanged = ( bWasVis != bShow );
3182 :
3183 0 : SetRowHidden(nStartRow, nEndRow, !bShow);
3184 0 : if (bShow)
3185 0 : SetRowFiltered(nStartRow, nEndRow, false);
3186 :
3187 0 : if ( bChanged )
3188 : {
3189 0 : ScChartListenerCollection* pCharts = pDocument->GetChartListenerCollection();
3190 0 : if ( pCharts )
3191 0 : pCharts->SetRangeDirty(ScRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ));
3192 :
3193 0 : InvalidatePageBreaks();
3194 : }
3195 :
3196 0 : nStartRow = nEndRow + 1;
3197 : }
3198 :
3199 0 : if ( !bHasObjects )
3200 : {
3201 : // #i116164# set the flags for the whole range at once
3202 0 : SetRowHidden(nRow1, nRow2, !bShow);
3203 0 : if (bShow)
3204 0 : SetRowFiltered(nRow1, nRow2, false);
3205 : }
3206 0 : }
3207 :
3208 0 : bool ScTable::IsDataFiltered(SCCOL nColStart, SCROW nRowStart, SCCOL nColEnd, SCROW nRowEnd) const
3209 : {
3210 0 : for (SCROW i = nRowStart; i <= nRowEnd; ++i)
3211 : {
3212 0 : if (RowHidden(i))
3213 0 : return true;
3214 : }
3215 0 : for (SCCOL i = nColStart; i <= nColEnd; ++i)
3216 : {
3217 0 : if (ColHidden(i))
3218 0 : return true;
3219 : }
3220 0 : return false;
3221 : }
3222 :
3223 0 : bool ScTable::IsDataFiltered(const ScRange& rRange) const
3224 : {
3225 0 : return IsDataFiltered(rRange.aStart.Col(), rRange.aStart.Row(),
3226 0 : rRange.aEnd.Col(), rRange.aEnd.Row());
3227 : }
3228 :
3229 0 : void ScTable::SetRowFlags( SCROW nRow, sal_uInt8 nNewFlags )
3230 : {
3231 0 : if (ValidRow(nRow) && pRowFlags)
3232 0 : pRowFlags->SetValue( nRow, nNewFlags);
3233 : else
3234 : {
3235 : OSL_FAIL("Invalid row number or no flags");
3236 : }
3237 0 : }
3238 :
3239 :
3240 0 : void ScTable::SetRowFlags( SCROW nStartRow, SCROW nEndRow, sal_uInt8 nNewFlags )
3241 : {
3242 0 : if (ValidRow(nStartRow) && ValidRow(nEndRow) && pRowFlags)
3243 0 : pRowFlags->SetValue( nStartRow, nEndRow, nNewFlags);
3244 : else
3245 : {
3246 : OSL_FAIL("Invalid row number(s) or no flags");
3247 : }
3248 0 : }
3249 :
3250 :
3251 0 : sal_uInt8 ScTable::GetColFlags( SCCOL nCol ) const
3252 : {
3253 0 : if (ValidCol(nCol) && pColFlags)
3254 0 : return pColFlags[nCol];
3255 : else
3256 0 : return 0;
3257 : }
3258 :
3259 :
3260 0 : sal_uInt8 ScTable::GetRowFlags( SCROW nRow ) const
3261 : {
3262 0 : if (ValidRow(nRow) && pRowFlags)
3263 0 : return pRowFlags->GetValue(nRow);
3264 : else
3265 0 : return 0;
3266 : }
3267 :
3268 :
3269 0 : SCROW ScTable::GetLastFlaggedRow() const
3270 : {
3271 0 : SCROW nLastFound = 0;
3272 0 : if (pRowFlags)
3273 : {
3274 0 : SCROW nRow = pRowFlags->GetLastAnyBitAccess( 0, sal::static_int_cast<sal_uInt8>(CR_ALL) );
3275 0 : if (ValidRow(nRow))
3276 0 : nLastFound = nRow;
3277 : }
3278 :
3279 0 : if (!maRowManualBreaks.empty())
3280 0 : nLastFound = ::std::max(nLastFound, *maRowManualBreaks.rbegin());
3281 :
3282 0 : if (mpHiddenRows)
3283 : {
3284 0 : SCROW nRow = mpHiddenRows->findLastNotOf(false);
3285 0 : if (ValidRow(nRow))
3286 0 : nLastFound = ::std::max(nLastFound, nRow);
3287 : }
3288 :
3289 0 : if (mpFilteredRows)
3290 : {
3291 0 : SCROW nRow = mpFilteredRows->findLastNotOf(false);
3292 0 : if (ValidRow(nRow))
3293 0 : nLastFound = ::std::max(nLastFound, nRow);
3294 : }
3295 :
3296 0 : return nLastFound;
3297 : }
3298 :
3299 :
3300 0 : SCCOL ScTable::GetLastChangedCol() const
3301 : {
3302 0 : if ( !pColFlags )
3303 0 : return 0;
3304 :
3305 0 : SCCOL nLastFound = 0;
3306 0 : for (SCCOL nCol = 1; nCol <= MAXCOL; nCol++)
3307 0 : if ((pColFlags[nCol] & CR_ALL) || (pColWidth[nCol] != STD_COL_WIDTH))
3308 0 : nLastFound = nCol;
3309 :
3310 0 : return nLastFound;
3311 : }
3312 :
3313 :
3314 0 : SCROW ScTable::GetLastChangedRow() const
3315 : {
3316 0 : if ( !pRowFlags )
3317 0 : return 0;
3318 :
3319 0 : SCROW nLastFlags = GetLastFlaggedRow();
3320 :
3321 : // Find the last row position where the height is NOT the standard row
3322 : // height.
3323 : // KOHEI: Test this to make sure it does what it's supposed to.
3324 0 : SCROW nLastHeight = mpRowHeights->findLastNotOf(ScGlobal::nStdRowHeight);
3325 0 : if (!ValidRow(nLastHeight))
3326 0 : nLastHeight = 0;
3327 :
3328 0 : return std::max( nLastFlags, nLastHeight);
3329 : }
3330 :
3331 :
3332 0 : bool ScTable::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, bool bShow )
3333 : {
3334 0 : if (pOutlineTable && pColFlags)
3335 : {
3336 0 : ScBitMaskCompressedArray< SCCOLROW, sal_uInt8> aArray( MAXCOL, pColFlags, MAXCOLCOUNT);
3337 0 : return pOutlineTable->GetColArray()->ManualAction( nStartCol, nEndCol, bShow, *this, true );
3338 : }
3339 : else
3340 0 : return false;
3341 : }
3342 :
3343 :
3344 0 : bool ScTable::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, bool bShow )
3345 : {
3346 0 : if (pOutlineTable && pRowFlags)
3347 0 : return pOutlineTable->GetRowArray()->ManualAction( nStartRow, nEndRow, bShow, *this, false );
3348 : else
3349 0 : return false;
3350 : }
3351 :
3352 :
3353 0 : void ScTable::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
3354 : {
3355 : // Column-wise expansion
3356 :
3357 0 : while (rX1 > 0 && ColHidden(rX1-1))
3358 0 : --rX1;
3359 :
3360 0 : while (rX2 < MAXCOL && ColHidden(rX2+1))
3361 0 : ++rX2;
3362 :
3363 : // Row-wise expansion
3364 :
3365 0 : if (rY1 > 0)
3366 : {
3367 : ScFlatBoolRowSegments::RangeData aData;
3368 0 : if (mpHiddenRows->getRangeData(rY1-1, aData) && aData.mbValue)
3369 : {
3370 0 : SCROW nStartRow = aData.mnRow1;
3371 0 : if (ValidRow(nStartRow))
3372 0 : rY1 = nStartRow;
3373 : }
3374 : }
3375 0 : if (rY2 < MAXROW)
3376 : {
3377 0 : SCROW nEndRow = -1;
3378 0 : if (RowHidden(rY2+1, NULL, &nEndRow) && ValidRow(nEndRow))
3379 0 : rY2 = nEndRow;
3380 : }
3381 0 : }
3382 :
3383 :
3384 0 : void ScTable::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
3385 : {
3386 0 : while ( rX2>rX1 && ColHidden(rX2) )
3387 0 : --rX2;
3388 0 : while ( rX2>rX1 && ColHidden(rX1) )
3389 0 : ++rX1;
3390 :
3391 0 : if (rY1 < rY2)
3392 : {
3393 : ScFlatBoolRowSegments::RangeData aData;
3394 0 : if (mpHiddenRows->getRangeData(rY2, aData) && aData.mbValue)
3395 : {
3396 0 : SCROW nStartRow = aData.mnRow1;
3397 0 : if (ValidRow(nStartRow) && nStartRow >= rY1)
3398 0 : rY2 = nStartRow;
3399 : }
3400 : }
3401 :
3402 0 : if (rY1 < rY2)
3403 : {
3404 0 : SCROW nEndRow = -1;
3405 0 : if (RowHidden(rY1, NULL, &nEndRow) && ValidRow(nEndRow) && nEndRow <= rY2)
3406 0 : rY1 = nEndRow;
3407 : }
3408 0 : }
3409 :
3410 :
3411 : // Auto-Outline
3412 :
3413 : template< typename T >
3414 0 : short DiffSign( T a, T b )
3415 : {
3416 : return (a<b) ? -1 :
3417 0 : (a>b) ? 1 : 0;
3418 : }
3419 :
3420 : namespace {
3421 :
3422 : class OutlineArrayFinder
3423 : {
3424 : ScRange maRef;
3425 : SCCOL mnCol;
3426 : SCTAB mnTab;
3427 : ScOutlineArray* mpArray;
3428 : bool mbSizeChanged;
3429 :
3430 : public:
3431 0 : OutlineArrayFinder(const ScRange& rRef, SCCOL nCol, SCTAB nTab, ScOutlineArray* pArray, bool bSizeChanged) :
3432 : maRef(rRef), mnCol(nCol), mnTab(nTab), mpArray(pArray),
3433 0 : mbSizeChanged(bSizeChanged) {}
3434 :
3435 0 : bool operator() (size_t nRow, const ScFormulaCell* pCell)
3436 : {
3437 0 : SCROW nRow2 = static_cast<SCROW>(nRow);
3438 :
3439 0 : if (!pCell->HasRefListExpressibleAsOneReference(maRef))
3440 0 : return false;
3441 :
3442 0 : if (maRef.aStart.Row() != nRow2 || maRef.aEnd.Row() != nRow2 ||
3443 0 : maRef.aStart.Tab() != mnTab || maRef.aEnd.Tab() != mnTab)
3444 0 : return false;
3445 :
3446 0 : if (DiffSign(maRef.aStart.Col(), mnCol) != DiffSign(maRef.aEnd.Col(), mnCol))
3447 0 : return false;
3448 :
3449 0 : return mpArray->Insert(maRef.aStart.Col(), maRef.aEnd.Col(), mbSizeChanged);
3450 : }
3451 : };
3452 :
3453 : }
3454 :
3455 0 : void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
3456 : {
3457 : typedef mdds::flat_segment_tree<SCROW, bool> UsedRowsType;
3458 :
3459 0 : bool bSizeChanged = false;
3460 :
3461 : SCCOL nCol;
3462 : SCROW nRow;
3463 : bool bFound;
3464 : ScOutlineArray* pArray;
3465 0 : ScRange aRef;
3466 :
3467 0 : StartOutlineTable();
3468 :
3469 : // Zeilen
3470 :
3471 0 : UsedRowsType aUsed(0, MAXROW+1, false);
3472 0 : for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3473 0 : aCol[nCol].FindUsed(nStartRow, nEndRow, aUsed);
3474 0 : aUsed.build_tree();
3475 :
3476 0 : pArray = pOutlineTable->GetRowArray();
3477 0 : for (nRow=nStartRow; nRow<=nEndRow; nRow++)
3478 : {
3479 0 : bool bUsed = false;
3480 0 : SCROW nLastRow = nRow;
3481 0 : aUsed.search_tree(nRow, bUsed, NULL, &nLastRow);
3482 0 : if (!bUsed)
3483 : {
3484 0 : nRow = nLastRow;
3485 0 : continue;
3486 : }
3487 :
3488 0 : bFound = false;
3489 0 : for (nCol=nStartCol; nCol<=nEndCol && !bFound; nCol++)
3490 : {
3491 0 : ScRefCellValue aCell = aCol[nCol].GetCellValue(nRow);
3492 :
3493 0 : if (aCell.meType != CELLTYPE_FORMULA)
3494 0 : continue;
3495 :
3496 0 : if (!aCell.mpFormula->HasRefListExpressibleAsOneReference(aRef))
3497 0 : continue;
3498 :
3499 0 : if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol &&
3500 0 : aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab &&
3501 0 : DiffSign( aRef.aStart.Row(), nRow ) ==
3502 0 : DiffSign( aRef.aEnd.Row(), nRow ) )
3503 : {
3504 0 : if (pArray->Insert( aRef.aStart.Row(), aRef.aEnd.Row(), bSizeChanged ))
3505 : {
3506 0 : bFound = true;
3507 : }
3508 : }
3509 0 : }
3510 : }
3511 :
3512 : // Column
3513 0 : pArray = pOutlineTable->GetColArray();
3514 0 : for (nCol=nStartCol; nCol<=nEndCol; nCol++)
3515 : {
3516 0 : if (aCol[nCol].IsEmptyData())
3517 0 : continue;
3518 :
3519 0 : OutlineArrayFinder aFunc(aRef, nCol, nTab, pArray, bSizeChanged);
3520 0 : sc::FindFormula(aCol[nCol].maCells, nStartRow, nEndRow, aFunc);
3521 0 : }
3522 0 : }
3523 :
3524 : // CopyData - fuer Query in anderen Bereich
3525 :
3526 0 : void ScTable::CopyData( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
3527 : SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab )
3528 : {
3529 : //! wenn fuer mehrere Zeilen benutzt, nach Spalten optimieren!
3530 :
3531 0 : ScAddress aSrc( nStartCol, nStartRow, nTab );
3532 0 : ScAddress aDest( nDestCol, nDestRow, nDestTab );
3533 0 : ScRange aRange( aSrc, aDest );
3534 0 : bool bThisTab = ( nDestTab == nTab );
3535 0 : SCROW nDestY = nDestRow;
3536 0 : for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
3537 : {
3538 0 : aSrc.SetRow( nRow );
3539 0 : aDest.SetRow( nDestY );
3540 0 : SCCOL nDestX = nDestCol;
3541 0 : for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
3542 : {
3543 0 : aSrc.SetCol( nCol );
3544 0 : aDest.SetCol( nDestX );
3545 0 : ScCellValue aCell;
3546 0 : aCell.assign(*pDocument, ScAddress(nCol, nRow, nTab));
3547 :
3548 0 : if (aCell.meType == CELLTYPE_FORMULA)
3549 : {
3550 0 : sc::RefUpdateContext aCxt(*pDocument);
3551 0 : aCxt.meMode = URM_COPY;
3552 0 : aCxt.maRange = aRange;
3553 0 : aCxt.mnColDelta = nDestCol - nStartCol;
3554 0 : aCxt.mnRowDelta = nDestRow - nStartRow;
3555 0 : aCxt.mnTabDelta = nDestTab - nTab;
3556 0 : aCell.mpFormula->UpdateReference(aCxt);
3557 0 : aCell.mpFormula->aPos = aDest;
3558 : }
3559 :
3560 0 : if (bThisTab)
3561 : {
3562 0 : aCell.release(aCol[nDestX], nDestY);
3563 0 : SetPattern( nDestX, nDestY, *GetPattern( nCol, nRow ), true );
3564 : }
3565 : else
3566 : {
3567 0 : aCell.release(*pDocument, aDest);
3568 0 : pDocument->SetPattern( aDest, *GetPattern( nCol, nRow ), true );
3569 : }
3570 :
3571 0 : ++nDestX;
3572 0 : }
3573 0 : ++nDestY;
3574 : }
3575 0 : }
3576 :
3577 :
3578 0 : bool ScTable::RefVisible(ScFormulaCell* pCell)
3579 : {
3580 0 : ScRange aRef;
3581 :
3582 0 : if (pCell->HasOneReference(aRef))
3583 : {
3584 0 : if (aRef.aStart.Col()==aRef.aEnd.Col() && aRef.aStart.Tab()==aRef.aEnd.Tab())
3585 : {
3586 : SCROW nEndRow;
3587 0 : if (!RowFiltered(aRef.aStart.Row(), NULL, &nEndRow))
3588 : // row not filtered.
3589 0 : nEndRow = ::std::numeric_limits<SCROW>::max();
3590 :
3591 0 : if (!ValidRow(nEndRow) || nEndRow < aRef.aEnd.Row())
3592 0 : return true; // at least partly visible
3593 0 : return false; // completely invisible
3594 : }
3595 : }
3596 :
3597 0 : return true; // irgendwie anders
3598 : }
3599 :
3600 :
3601 0 : void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, OUString& rStr)
3602 : {
3603 0 : GetInputString(nCol, nRow, rStr);
3604 0 : rStr = ScGlobal::pCharClass->uppercase(rStr.trim());
3605 0 : }
3606 :
3607 :
3608 : // Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage
3609 :
3610 0 : void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos)
3611 : {
3612 0 : ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
3613 0 : if( pDrawLayer )
3614 : {
3615 0 : double fValX = GetColOffset( MAXCOL + 1 ) * HMM_PER_TWIPS;
3616 0 : double fValY = GetRowOffset( MAXROW + 1 ) * HMM_PER_TWIPS;
3617 0 : const long nMax = ::std::numeric_limits<long>::max();
3618 : // #i113884# Avoid int32 overflow with possible negative results than can cause bad effects.
3619 : // If the draw page size is smaller than all rows, only the bottom of the sheet is affected.
3620 0 : long x = ( fValX > (double)nMax ) ? nMax : (long) fValX;
3621 0 : long y = ( fValY > (double)nMax ) ? nMax : (long) fValY;
3622 :
3623 0 : if ( IsLayoutRTL() ) // IsNegativePage
3624 0 : x = -x;
3625 :
3626 0 : pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( x, y ), bUpdateNoteCaptionPos );
3627 : }
3628 :
3629 : // #i102616# actions that modify the draw page size count as sheet modification
3630 : // (exception: InitDrawLayer)
3631 0 : if (bResetStreamValid && IsStreamValid())
3632 0 : SetStreamValid(false);
3633 0 : }
3634 :
3635 0 : void ScTable::SetRangeName(ScRangeName* pNew)
3636 : {
3637 0 : delete mpRangeName;
3638 0 : mpRangeName = pNew;
3639 :
3640 : //fdo#39792: mark stream as invalid, otherwise new ScRangeName will not be written to file
3641 0 : if (IsStreamValid())
3642 0 : SetStreamValid(false);
3643 0 : }
3644 :
3645 0 : ScRangeName* ScTable::GetRangeName() const
3646 : {
3647 0 : if (!mpRangeName)
3648 0 : mpRangeName = new ScRangeName;
3649 0 : return mpRangeName;
3650 : }
3651 :
3652 :
3653 0 : sal_uLong ScTable::GetRowOffset( SCROW nRow, bool bHiddenAsZero ) const
3654 : {
3655 0 : sal_uLong n = 0;
3656 0 : if ( mpHiddenRows && mpRowHeights )
3657 : {
3658 0 : if (nRow == 0)
3659 0 : return 0;
3660 0 : else if (nRow == 1)
3661 0 : return GetRowHeight(0, NULL, NULL, bHiddenAsZero );
3662 :
3663 0 : n = GetTotalRowHeight(0, nRow-1, bHiddenAsZero);
3664 : #if OSL_DEBUG_LEVEL > 0
3665 : if (n == ::std::numeric_limits<unsigned long>::max())
3666 : OSL_FAIL("ScTable::GetRowOffset: row heights overflow");
3667 : #endif
3668 : }
3669 : else
3670 : {
3671 : OSL_FAIL("GetRowOffset: Data missing");
3672 : }
3673 0 : return n;
3674 : }
3675 :
3676 0 : SCROW ScTable::GetRowForHeight(sal_uLong nHeight) const
3677 : {
3678 0 : sal_uInt32 nSum = 0;
3679 :
3680 : ScFlatBoolRowSegments::RangeData aData;
3681 0 : for (SCROW nRow = 0; nRow <= MAXROW; ++nRow)
3682 : {
3683 0 : if (!mpHiddenRows->getRangeData(nRow, aData))
3684 0 : break;
3685 :
3686 0 : if (aData.mbValue)
3687 : {
3688 0 : nRow = aData.mnRow2;
3689 0 : continue;
3690 : }
3691 :
3692 0 : sal_uInt32 nNew = mpRowHeights->getValue(nRow);
3693 0 : nSum += nNew;
3694 0 : if (nSum > nHeight)
3695 : {
3696 0 : return nRow < MAXROW ? nRow + 1 : MAXROW;
3697 : }
3698 : }
3699 0 : return -1;
3700 : }
3701 :
3702 :
3703 0 : sal_uLong ScTable::GetColOffset( SCCOL nCol, bool bHiddenAsZero ) const
3704 : {
3705 0 : sal_uLong n = 0;
3706 0 : if ( pColWidth )
3707 : {
3708 : SCCOL i;
3709 0 : for( i = 0; i < nCol; i++ )
3710 0 : if (!( bHiddenAsZero && ColHidden(i) ))
3711 0 : n += pColWidth[i];
3712 : }
3713 : else
3714 : {
3715 : OSL_FAIL("GetColumnOffset: Data missing");
3716 : }
3717 0 : return n;
3718 0 : }
3719 :
3720 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|