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