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