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