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