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