1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 // INCLUDE --------------------------------------------------------------- 32 33 #include "scitems.hxx" 34 #include "collect.hxx" 35 #include "attrib.hxx" 36 #include "patattr.hxx" 37 #include "docpool.hxx" 38 #include "cell.hxx" 39 #include "table.hxx" 40 #include "column.hxx" 41 #include "document.hxx" 42 #include "drwlayer.hxx" 43 #include "olinetab.hxx" 44 #include "userlist.hxx" 45 #include "stlsheet.hxx" 46 #include "global.hxx" 47 #include "rechead.hxx" 48 #include "stlpool.hxx" 49 #include "stlsheet.hxx" 50 #include "brdcst.hxx" 51 #include "tabprotection.hxx" 52 #include "globstr.hrc" 53 #include "segmenttree.hxx" 54 #include <com/sun/star/sheet/TablePageBreakData.hpp> 55 56 #include <algorithm> 57 #include <limits> 58 59 using ::com::sun::star::uno::Sequence; 60 using ::com::sun::star::sheet::TablePageBreakData; 61 using ::std::set; 62 63 // STATIC DATA ----------------------------------------------------------- 64 65 #define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue() 66 67 68 void ScTable::UpdatePageBreaks( const ScRange* pUserArea ) 69 { 70 if ( pDocument->IsImportingXML() ) 71 return; 72 73 // pUserArea != NULL -> print area is specified. We need to force-update 74 // the page breaks. 75 76 if (!pUserArea) 77 { 78 if (!bPageSizeValid) 79 return; 80 81 if (mbPageBreaksValid) 82 return; 83 } 84 85 SfxStyleSheetBase* pStyle = pDocument->GetStyleSheetPool()-> 86 Find( aPageStyle, SFX_STYLE_FAMILY_PAGE ); 87 if ( !pStyle ) 88 { 89 DBG_ERROR("UpdatePageBreaks: Style nicht gefunden"); 90 return; 91 } 92 SfxItemSet* pStyleSet = &pStyle->GetItemSet(); 93 const SfxPoolItem* pItem; 94 95 SCCOL nX; 96 SCCOL nStartCol = 0; 97 SCROW nStartRow = 0; 98 SCCOL nEndCol = MAXCOL; 99 SCROW nEndRow = MAXROW; 100 if (pUserArea) 101 { 102 nStartCol = pUserArea->aStart.Col(); 103 nStartRow = pUserArea->aStart.Row(); 104 nEndCol = pUserArea->aEnd.Col(); 105 nEndRow = pUserArea->aEnd.Row(); 106 } 107 else 108 { 109 sal_uInt16 nAreaCount = GetPrintRangeCount(); 110 if ( nAreaCount > 1 ) 111 { 112 // bei mehreren Bereichen nichts anzeigen: 113 114 for (nX=0; nX<MAXCOL; nX++) 115 RemoveColBreak(nX, true, false); 116 117 RemoveRowPageBreaks(0, MAXROW-1); 118 119 return; 120 } 121 else if ( nAreaCount == 1 ) 122 { 123 const ScRange* pArea = GetPrintRange( 0 ); 124 if (pArea) 125 { 126 nStartCol = pArea->aStart.Col(); 127 nStartRow = pArea->aStart.Row(); 128 nEndCol = pArea->aEnd.Col(); 129 nEndRow = pArea->aEnd.Row(); 130 } 131 } // sonst alles 132 } 133 134 // get bSkipColBreaks/bSkipRowBreaks flags: 135 136 bool bSkipColBreaks = false; 137 bool bSkipRowBreaks = false; 138 139 if ( pStyleSet->GetItemState( ATTR_PAGE_SCALETOPAGES, sal_False, &pItem ) == SFX_ITEM_SET ) 140 { 141 DBG_ASSERT( pItem->ISA(SfxUInt16Item), "falsches Item" ); 142 bSkipColBreaks = bSkipRowBreaks = ( ((const SfxUInt16Item*)pItem)->GetValue() > 0 ); 143 } 144 145 if ( !bSkipColBreaks && pStyleSet->GetItemState(ATTR_PAGE_SCALETO, sal_False, &pItem) == SFX_ITEM_SET ) 146 { 147 // #i54993# when fitting to width or height, ignore only manual breaks in that direction 148 const ScPageScaleToItem* pScaleToItem = static_cast<const ScPageScaleToItem*>(pItem); 149 if ( pScaleToItem->GetWidth() > 0 ) 150 bSkipColBreaks = true; 151 if ( pScaleToItem->GetHeight() > 0 ) 152 bSkipRowBreaks = true; 153 } 154 155 //-------------------------------------------------------------------------- 156 157 long nPageSizeX = aPageSizeTwips.Width(); 158 long nPageSizeY = aPageSizeTwips.Height(); 159 160 // Anfang: Breaks loeschen 161 162 for (nX=0; nX<nStartCol; nX++) 163 RemoveColBreak(nX, true, false); 164 RemoveRowPageBreaks(0, nStartRow-1); 165 166 if (nStartCol > 0) 167 SetColBreak(nStartCol, true, false); // AREABREAK 168 if (nStartRow > 0) 169 SetRowBreak(nStartRow, true, false); // AREABREAK 170 171 // Mittelteil: Breaks verteilen 172 173 sal_Bool bRepeatCol = ( nRepeatStartX != SCCOL_REPEAT_NONE ); 174 sal_Bool bColFound = sal_False; 175 long nSizeX = 0; 176 for (nX=nStartCol; nX<=nEndCol; nX++) 177 { 178 sal_Bool bStartOfPage = sal_False; 179 long nThisX = ColHidden(nX) ? 0 : pColWidth[nX]; 180 bool bManualBreak = HasColManualBreak(nX); 181 if ( (nSizeX+nThisX > nPageSizeX) || (bManualBreak && !bSkipColBreaks) ) 182 { 183 SetColBreak(nX, true, false); 184 nSizeX = 0; 185 bStartOfPage = sal_True; 186 } 187 else if (nX != nStartCol) 188 RemoveColBreak(nX, true, false); 189 else 190 bStartOfPage = sal_True; 191 192 if ( bStartOfPage && bRepeatCol && nX>nRepeatStartX && !bColFound ) 193 { 194 // subtract size of repeat columns from page size 195 for (SCCOL i=nRepeatStartX; i<=nRepeatEndX; i++) 196 nPageSizeX -= ColHidden(i) ? 0 : pColWidth[i]; 197 while (nX<=nRepeatEndX) 198 RemoveColBreak(++nX, true, false); 199 bColFound = sal_True; 200 } 201 202 nSizeX += nThisX; 203 } 204 205 // Remove all page breaks in range. 206 RemoveRowPageBreaks(nStartRow+1, nEndRow); 207 208 // And set new page breaks. 209 sal_Bool bRepeatRow = ( nRepeatStartY != SCROW_REPEAT_NONE ); 210 sal_Bool bRowFound = sal_False; 211 long nSizeY = 0; 212 ScFlatBoolRowSegments::ForwardIterator aIterHidden(*mpHiddenRows); 213 ScFlatUInt16RowSegments::ForwardIterator aIterHeights(*mpRowHeights); 214 SCROW nNextManualBreak = GetNextManualBreak(nStartRow); // -1 => no more manual breaks 215 for (SCROW nY = nStartRow; nY <= nEndRow; ++nY) 216 { 217 sal_Bool bStartOfPage = sal_False; 218 bool bThisRowHidden = false; 219 aIterHidden.getValue(nY, bThisRowHidden); 220 long nThisY = 0; 221 if (!bThisRowHidden) 222 { 223 sal_uInt16 nTmp; 224 aIterHeights.getValue(nY, nTmp); 225 nThisY = static_cast<long>(nTmp); 226 } 227 228 bool bManualBreak = false; 229 if (nNextManualBreak >= 0) 230 { 231 bManualBreak = (nY == nNextManualBreak); 232 if (nY >= nNextManualBreak) 233 // Query the next menual break position. 234 nNextManualBreak = GetNextManualBreak(nY+1); 235 } 236 237 if ( (nSizeY+nThisY > nPageSizeY) || (bManualBreak && !bSkipRowBreaks) ) 238 { 239 SetRowBreak(nY, true, false); 240 nSizeY = 0; 241 bStartOfPage = sal_True; 242 } 243 else if (nY != nStartRow) 244 ; // page break already removed 245 else 246 bStartOfPage = sal_True; 247 248 if ( bStartOfPage && bRepeatRow && nY>nRepeatStartY && !bRowFound ) 249 { 250 // subtract size of repeat rows from page size 251 unsigned long nHeights = GetTotalRowHeight(nRepeatStartY, nRepeatEndY); 252 #ifdef DBG_UTIL 253 if (nHeights == ::std::numeric_limits<unsigned long>::max()) 254 DBG_ERRORFILE("ScTable::UpdatePageBreaks: row heights overflow"); 255 #endif 256 nPageSizeY -= nHeights; 257 if (nY <= nRepeatEndY) 258 RemoveRowPageBreaks(nY, nRepeatEndY); 259 bRowFound = sal_True; 260 } 261 262 if (bThisRowHidden) 263 { 264 // Hidden row range. Skip them unless there is a manual break. 265 SCROW nLastCommon = aIterHidden.getLastPos(); 266 if (nNextManualBreak >= 0) 267 nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1); 268 nY = nLastCommon; 269 } 270 else 271 { 272 // Visible row range. 273 274 SCROW nLastHidden = aIterHidden.getLastPos(); 275 SCROW nLastHeight = aIterHeights.getLastPos(); 276 SCROW nLastCommon = ::std::min(nLastHidden, nLastHeight); 277 if (nNextManualBreak >= 0) 278 nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1); 279 280 if (nLastCommon > nY) 281 { 282 long nMaxMultiple = static_cast<long>(nLastCommon - nY); 283 long nMultiple = (nPageSizeY - nSizeY) / nThisY; 284 if (nMultiple > nMaxMultiple) 285 nMultiple = nMaxMultiple; 286 if (nMultiple > 1) 287 { 288 nSizeY += nThisY * (nMultiple - 1); 289 nY += nMultiple - 1; 290 } 291 } 292 } 293 294 nSizeY += nThisY; 295 } 296 297 // Ende: Breaks loeschen 298 299 if (nEndCol < MAXCOL) 300 { 301 SetColBreak(nEndCol+1, true, false); // AREABREAK 302 for (nX=nEndCol+2; nX<=MAXCOL; nX++) 303 RemoveColBreak(nX, true, false); 304 } 305 if (nEndRow < MAXROW) 306 { 307 SetRowBreak(nEndRow+1, true, false); // AREABREAK 308 if (nEndRow+2 <= MAXROW) 309 RemoveRowPageBreaks(nEndRow+2, MAXROW); 310 } 311 mbPageBreaksValid = !pUserArea; // #i116881# the valid flag can only apply to the "no user area" case 312 } 313 314 void ScTable::RemoveManualBreaks() 315 { 316 maRowManualBreaks.clear(); 317 maColManualBreaks.clear(); 318 InvalidatePageBreaks(); 319 320 if (IsStreamValid()) 321 SetStreamValid(sal_False); 322 } 323 324 sal_Bool ScTable::HasManualBreaks() const 325 { 326 return !maRowManualBreaks.empty() || !maColManualBreaks.empty(); 327 } 328 329 void ScTable::SetRowManualBreaks( const ::std::set<SCROW>& rBreaks ) 330 { 331 maRowManualBreaks = rBreaks; 332 InvalidatePageBreaks(); 333 if (IsStreamValid()) 334 SetStreamValid(sal_False); 335 } 336 337 void ScTable::SetColManualBreaks( const ::std::set<SCCOL>& rBreaks ) 338 { 339 maColManualBreaks = rBreaks; 340 InvalidatePageBreaks(); 341 if (IsStreamValid()) 342 SetStreamValid(sal_False); 343 } 344 345 void ScTable::GetAllRowBreaks(set<SCROW>& rBreaks, bool bPage, bool bManual) const 346 { 347 if (bPage) 348 rBreaks = maRowPageBreaks; 349 350 if (bManual) 351 { 352 using namespace std; 353 copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(rBreaks, rBreaks.begin())); 354 } 355 } 356 357 void ScTable::GetAllColBreaks(set<SCCOL>& rBreaks, bool bPage, bool bManual) const 358 { 359 if (bPage) 360 rBreaks = maColPageBreaks; 361 362 if (bManual) 363 { 364 using namespace std; 365 copy(maColManualBreaks.begin(), maColManualBreaks.end(), inserter(rBreaks, rBreaks.begin())); 366 } 367 } 368 369 bool ScTable::HasRowPageBreak(SCROW nRow) const 370 { 371 if (!ValidRow(nRow)) 372 return false; 373 374 return maRowPageBreaks.find(nRow) != maRowPageBreaks.end(); 375 } 376 377 bool ScTable::HasColPageBreak(SCCOL nCol) const 378 { 379 if (!ValidCol(nCol)) 380 return false; 381 382 return maColPageBreaks.find(nCol) != maColPageBreaks.end(); 383 } 384 385 bool ScTable::HasRowManualBreak(SCROW nRow) const 386 { 387 if (!ValidRow(nRow)) 388 return false; 389 390 return maRowManualBreaks.find(nRow) != maRowManualBreaks.end(); 391 } 392 393 bool ScTable::HasColManualBreak(SCCOL nCol) const 394 { 395 if (!ValidCol(nCol)) 396 return false; 397 398 return maColManualBreaks.find(nCol) != maColManualBreaks.end(); 399 } 400 401 SCROW ScTable::GetNextManualBreak(SCROW nRow) const 402 { 403 set<SCROW>::const_iterator itr = maRowManualBreaks.lower_bound(nRow); 404 return itr == maRowManualBreaks.end() ? -1 : *itr; 405 } 406 407 void ScTable::RemoveRowPageBreaks(SCROW nStartRow, SCROW nEndRow) 408 { 409 using namespace std; 410 411 if (!ValidRow(nStartRow) || !ValidRow(nEndRow)) 412 return; 413 414 set<SCROW>::iterator low = maRowPageBreaks.lower_bound(nStartRow); 415 set<SCROW>::iterator high = maRowPageBreaks.upper_bound(nEndRow); 416 maRowPageBreaks.erase(low, high); 417 } 418 419 void ScTable::RemoveRowBreak(SCROW nRow, bool bPage, bool bManual) 420 { 421 if (!ValidRow(nRow)) 422 return; 423 424 if (bPage) 425 maRowPageBreaks.erase(nRow); 426 427 if (bManual) 428 { 429 maRowManualBreaks.erase(nRow); 430 InvalidatePageBreaks(); 431 } 432 } 433 434 void ScTable::RemoveColBreak(SCCOL nCol, bool bPage, bool bManual) 435 { 436 if (!ValidCol(nCol)) 437 return; 438 439 if (bPage) 440 maColPageBreaks.erase(nCol); 441 442 if (bManual) 443 { 444 maColManualBreaks.erase(nCol); 445 InvalidatePageBreaks(); 446 } 447 } 448 449 void ScTable::SetRowBreak(SCROW nRow, bool bPage, bool bManual) 450 { 451 if (!ValidRow(nRow)) 452 return; 453 454 if (bPage) 455 maRowPageBreaks.insert(nRow); 456 457 if (bManual) 458 { 459 maRowManualBreaks.insert(nRow); 460 InvalidatePageBreaks(); 461 } 462 } 463 464 void ScTable::SetColBreak(SCCOL nCol, bool bPage, bool bManual) 465 { 466 if (!ValidCol(nCol)) 467 return; 468 469 if (bPage) 470 maColPageBreaks.insert(nCol); 471 472 if (bManual) 473 { 474 maColManualBreaks.insert(nCol); 475 InvalidatePageBreaks(); 476 } 477 } 478 479 Sequence<TablePageBreakData> ScTable::GetRowBreakData() const 480 { 481 using ::std::copy; 482 using ::std::inserter; 483 484 set<SCROW> aRowBreaks = maRowPageBreaks; 485 copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(aRowBreaks, aRowBreaks.begin())); 486 487 set<SCROW>::const_iterator itr = aRowBreaks.begin(), itrEnd = aRowBreaks.end(); 488 Sequence<TablePageBreakData> aSeq(aRowBreaks.size()); 489 490 for (sal_Int32 i = 0; itr != itrEnd; ++itr, ++i) 491 { 492 SCROW nRow = *itr; 493 TablePageBreakData aData; 494 aData.Position = nRow; 495 aData.ManualBreak = HasRowManualBreak(nRow); 496 aSeq[i] = aData; 497 } 498 499 return aSeq; 500 } 501 502 bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const 503 { 504 if (!ValidRow(nRow)) 505 { 506 if (pFirstRow) 507 *pFirstRow = nRow; 508 if (pLastRow) 509 *pLastRow = nRow; 510 return true; 511 } 512 513 ScFlatBoolRowSegments::RangeData aData; 514 if (!mpHiddenRows->getRangeData(nRow, aData)) 515 { 516 // search failed. 517 if (pFirstRow) 518 *pFirstRow = nRow; 519 if (pLastRow) 520 *pLastRow = nRow; 521 return true; 522 } 523 524 if (pFirstRow) 525 *pFirstRow = aData.mnRow1; 526 if (pLastRow) 527 *pLastRow = aData.mnRow2; 528 529 return aData.mbValue; 530 } 531 532 533 bool ScTable::RowHidden(SCROW nRow, SCROW& rLastRow) const 534 { 535 rLastRow = nRow; 536 if (!ValidRow(nRow)) 537 return true; 538 539 ScFlatBoolRowSegments::RangeData aData; 540 if (!mpHiddenRows->getRangeData(nRow, aData)) 541 // search failed. 542 return true; 543 544 rLastRow = aData.mnRow2; 545 return aData.mbValue; 546 } 547 548 bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) const 549 { 550 SCROW nRow = nStartRow; 551 while (nRow <= nEndRow) 552 { 553 SCROW nLastRow = -1; 554 bool bHidden = RowHidden(nRow, nLastRow); 555 if (bHidden) 556 return true; 557 558 nRow = nLastRow + 1; 559 } 560 return false; 561 } 562 563 bool ScTable::ColHidden(SCCOL nCol, SCCOL& rLastCol) const 564 { 565 rLastCol = nCol; 566 if (!ValidCol(nCol)) 567 return true; 568 569 ScFlatBoolColSegments::RangeData aData; 570 if (!mpHiddenCols->getRangeData(nCol, aData)) 571 return true; 572 573 rLastCol = aData.mnCol2; 574 return aData.mbValue; 575 } 576 577 bool ScTable::ColHidden(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const 578 { 579 if (!ValidCol(nCol)) 580 return true; 581 582 ScFlatBoolColSegments::RangeData aData; 583 if (!mpHiddenCols->getRangeData(nCol, aData)) 584 return true; 585 586 if (pFirstCol) 587 *pFirstCol = aData.mnCol1; 588 if (pLastCol) 589 *pLastCol = aData.mnCol2; 590 591 return aData.mbValue; 592 } 593 594 void ScTable::SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden) 595 { 596 if (bHidden) 597 mpHiddenRows->setTrue(nStartRow, nEndRow); 598 else 599 mpHiddenRows->setFalse(nStartRow, nEndRow); 600 } 601 602 void ScTable::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden) 603 { 604 if (bHidden) 605 mpHiddenCols->setTrue(nStartCol, nEndCol); 606 else 607 mpHiddenCols->setFalse(nStartCol, nEndCol); 608 } 609 610 void ScTable::CopyColHidden(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol) 611 { 612 SCCOL nCol = nStartCol; 613 while (nCol <= nEndCol) 614 { 615 SCCOL nLastCol; 616 bool bHidden = rTable.ColHidden(nCol, NULL, &nLastCol); 617 if (nLastCol > nEndCol) 618 nLastCol = nEndCol; 619 620 SetColHidden(nCol, nLastCol, bHidden); 621 nCol = nLastCol + 1; 622 } 623 } 624 625 void ScTable::CopyRowHidden(ScTable& rTable, SCROW nStartRow, SCROW nEndRow) 626 { 627 SCROW nRow = nStartRow; 628 while (nRow <= nEndRow) 629 { 630 SCROW nLastRow = -1; 631 bool bHidden = rTable.RowHidden(nRow, nLastRow); 632 if (nLastRow > nEndRow) 633 nLastRow = nEndRow; 634 SetRowHidden(nRow, nLastRow, bHidden); 635 nRow = nLastRow + 1; 636 } 637 } 638 639 void ScTable::CopyRowHeight(ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow, SCROW nSrcOffset) 640 { 641 SCROW nRow = nStartRow; 642 ScFlatUInt16RowSegments::RangeData aSrcData; 643 while (nRow <= nEndRow) 644 { 645 if (!rSrcTable.mpRowHeights->getRangeData(nRow + nSrcOffset, aSrcData)) 646 // Something is wrong ! 647 return; 648 649 SCROW nLastRow = aSrcData.mnRow2 - nSrcOffset; 650 if (nLastRow > nEndRow) 651 nLastRow = nEndRow; 652 653 mpRowHeights->setValue(nRow, nLastRow, aSrcData.mnValue); 654 nRow = nLastRow + 1; 655 } 656 } 657 658 SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) const 659 { 660 SCROW nRow = nStartRow; 661 ScFlatBoolRowSegments::RangeData aData; 662 while (nRow <= nEndRow) 663 { 664 if (!ValidRow(nRow)) 665 break; 666 667 if (!mpHiddenRows->getRangeData(nRow, aData)) 668 // failed to get range data. 669 break; 670 671 if (!aData.mbValue) 672 // visible row found 673 return nRow; 674 675 nRow = aData.mnRow2 + 1; 676 } 677 678 return ::std::numeric_limits<SCROW>::max(); 679 } 680 681 SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) const 682 { 683 SCROW nRow = nEndRow; 684 ScFlatBoolRowSegments::RangeData aData; 685 while (nRow >= nStartRow) 686 { 687 if (!ValidRow(nRow)) 688 break; 689 690 if (!mpHiddenRows->getRangeData(nRow, aData)) 691 // failed to get range data. 692 break; 693 694 if (!aData.mbValue) 695 // visible row found 696 return nRow; 697 698 nRow = aData.mnRow1 - 1; 699 } 700 701 return ::std::numeric_limits<SCROW>::max(); 702 } 703 704 SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) const 705 { 706 SCROW nCount = 0; 707 SCROW nRow = nStartRow; 708 ScFlatBoolRowSegments::RangeData aData; 709 while (nRow <= nEndRow) 710 { 711 if (!mpHiddenRows->getRangeData(nRow, aData)) 712 break; 713 714 if (aData.mnRow2 > nEndRow) 715 aData.mnRow2 = nEndRow; 716 717 if (!aData.mbValue) 718 nCount += aData.mnRow2 - nRow + 1; 719 720 nRow = aData.mnRow2 + 1; 721 } 722 return nCount; 723 } 724 725 sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow) const 726 { 727 sal_uInt32 nHeight = 0; 728 SCROW nRow = nStartRow; 729 ScFlatBoolRowSegments::RangeData aData; 730 while (nRow <= nEndRow) 731 { 732 if (!mpHiddenRows->getRangeData(nRow, aData)) 733 break; 734 735 if (aData.mnRow2 > nEndRow) 736 aData.mnRow2 = nEndRow; 737 738 if (!aData.mbValue) 739 // visible row range. 740 nHeight += mpRowHeights->getSumValue(nRow, aData.mnRow2); 741 742 nRow = aData.mnRow2 + 1; 743 } 744 745 return nHeight; 746 } 747 748 SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) const 749 { 750 if (bCol) 751 { 752 SCCOL nCol = static_cast<SCCOL>(nPos); 753 if (ColHidden(nCol)) 754 { 755 for (SCCOL i = nCol+1; i <= MAXCOL; ++i) 756 { 757 if (!ColHidden(nCol)) 758 return nCol - 1; 759 } 760 } 761 } 762 else 763 { 764 SCROW nRow = static_cast<SCROW>(nPos); 765 SCROW nLastRow; 766 if (RowHidden(nRow, NULL, &nLastRow)) 767 return static_cast<SCCOLROW>(nLastRow); 768 } 769 return ::std::numeric_limits<SCCOLROW>::max(); 770 } 771 772 bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const 773 { 774 if (!ValidRow(nRow)) 775 return false; 776 777 ScFlatBoolRowSegments::RangeData aData; 778 if (!mpFilteredRows->getRangeData(nRow, aData)) 779 // search failed. 780 return false; 781 782 if (pFirstRow) 783 *pFirstRow = aData.mnRow1; 784 if (pLastRow) 785 *pLastRow = aData.mnRow2; 786 787 return aData.mbValue; 788 } 789 790 bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const 791 { 792 if (!ValidCol(nCol)) 793 return false; 794 795 ScFlatBoolColSegments::RangeData aData; 796 if (!mpFilteredCols->getRangeData(nCol, aData)) 797 // search failed. 798 return false; 799 800 if (pFirstCol) 801 *pFirstCol = aData.mnCol1; 802 if (pLastCol) 803 *pLastCol = aData.mnCol2; 804 805 return aData.mbValue; 806 } 807 808 bool ScTable::HasFilteredRows(SCROW nStartRow, SCROW nEndRow) const 809 { 810 SCROW nRow = nStartRow; 811 while (nRow <= nEndRow) 812 { 813 SCROW nLastRow = nRow; 814 bool bFiltered = RowFiltered(nRow, NULL, &nLastRow); 815 if (bFiltered) 816 return true; 817 818 nRow = nLastRow + 1; 819 } 820 return false; 821 } 822 823 void ScTable::CopyColFiltered(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol) 824 { 825 SCCOL nCol = nStartCol; 826 while (nCol <= nEndCol) 827 { 828 SCCOL nLastCol; 829 bool bFiltered = rTable.ColFiltered(nCol, NULL, &nLastCol); 830 if (nLastCol > nEndCol) 831 nLastCol = nEndCol; 832 833 SetColFiltered(nCol, nLastCol, bFiltered); 834 nCol = nLastCol + 1; 835 } 836 } 837 838 void ScTable::CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow) 839 { 840 SCROW nRow = nStartRow; 841 while (nRow <= nEndRow) 842 { 843 SCROW nLastRow = -1; 844 bool bFiltered = rTable.RowFiltered(nRow, NULL, &nLastRow); 845 if (nLastRow > nEndRow) 846 nLastRow = nEndRow; 847 SetRowFiltered(nRow, nLastRow, bFiltered); 848 nRow = nLastRow + 1; 849 } 850 } 851 852 void ScTable::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered) 853 { 854 if (bFiltered) 855 mpFilteredRows->setTrue(nStartRow, nEndRow); 856 else 857 mpFilteredRows->setFalse(nStartRow, nEndRow); 858 } 859 860 void ScTable::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered) 861 { 862 if (bFiltered) 863 mpFilteredCols->setTrue(nStartCol, nEndCol); 864 else 865 mpFilteredCols->setFalse(nStartCol, nEndCol); 866 } 867 868 SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const 869 { 870 SCROW nRow = nStartRow; 871 ScFlatBoolRowSegments::RangeData aData; 872 while (nRow <= nEndRow) 873 { 874 if (!ValidRow(nRow)) 875 break; 876 877 if (!mpFilteredRows->getRangeData(nRow, aData)) 878 // failed to get range data. 879 break; 880 881 if (!aData.mbValue) 882 // non-filtered row found 883 return nRow; 884 885 nRow = aData.mnRow2 + 1; 886 } 887 888 return ::std::numeric_limits<SCROW>::max(); 889 } 890 891 SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const 892 { 893 SCROW nRow = nEndRow; 894 ScFlatBoolRowSegments::RangeData aData; 895 while (nRow >= nStartRow) 896 { 897 if (!ValidRow(nRow)) 898 break; 899 900 if (!mpFilteredRows->getRangeData(nRow, aData)) 901 // failed to get range data. 902 break; 903 904 if (!aData.mbValue) 905 // non-filtered row found 906 return nRow; 907 908 nRow = aData.mnRow1 - 1; 909 } 910 911 return ::std::numeric_limits<SCROW>::max(); 912 } 913 914 SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) const 915 { 916 SCROW nCount = 0; 917 SCROW nRow = nStartRow; 918 ScFlatBoolRowSegments::RangeData aData; 919 while (nRow <= nEndRow) 920 { 921 if (!mpFilteredRows->getRangeData(nRow, aData)) 922 break; 923 924 if (aData.mnRow2 > nEndRow) 925 aData.mnRow2 = nEndRow; 926 927 if (!aData.mbValue) 928 nCount += aData.mnRow2 - nRow + 1; 929 930 nRow = aData.mnRow2 + 1; 931 } 932 return nCount; 933 } 934 935 namespace { 936 937 void lcl_syncFlags(ScFlatBoolColSegments& rColSegments, ScFlatBoolRowSegments& rRowSegments, 938 sal_uInt8* pColFlags, ScBitMaskCompressedArray< SCROW, sal_uInt8>* pRowFlags, const sal_uInt8 nFlagMask) 939 { 940 using ::sal::static_int_cast; 941 942 pRowFlags->AndValue(0, MAXROW, static_int_cast<sal_uInt8>(~nFlagMask)); 943 for (SCCOL i = 0; i <= MAXCOL; ++i) 944 pColFlags[i] &= static_int_cast<sal_uInt8>(~nFlagMask); 945 946 { 947 // row hidden flags. 948 949 SCROW nRow = 0; 950 ScFlatBoolRowSegments::RangeData aData; 951 while (nRow <= MAXROW) 952 { 953 if (!rRowSegments.getRangeData(nRow, aData)) 954 break; 955 956 if (aData.mbValue) 957 pRowFlags->OrValue(nRow, aData.mnRow2, static_int_cast<sal_uInt8>(nFlagMask)); 958 959 nRow = aData.mnRow2 + 1; 960 } 961 } 962 963 { 964 // column hidden flags. 965 966 SCCOL nCol = 0; 967 ScFlatBoolColSegments::RangeData aData; 968 while (nCol <= MAXCOL) 969 { 970 if (!rColSegments.getRangeData(nCol, aData)) 971 break; 972 973 if (aData.mbValue) 974 { 975 for (SCCOL i = nCol; i <= aData.mnCol2; ++i) 976 pColFlags[i] |= nFlagMask; 977 } 978 979 nCol = aData.mnCol2 + 1; 980 } 981 } 982 } 983 984 } 985 986 void ScTable::SyncColRowFlags() 987 { 988 using ::sal::static_int_cast; 989 990 // Manual breaks. 991 pRowFlags->AndValue(0, MAXROW, static_int_cast<sal_uInt8>(~CR_MANUALBREAK)); 992 for (SCCOL i = 0; i <= MAXCOL; ++i) 993 pColFlags[i] &= static_int_cast<sal_uInt8>(~CR_MANUALBREAK); 994 995 if (!maRowManualBreaks.empty()) 996 { 997 for (set<SCROW>::const_iterator itr = maRowManualBreaks.begin(), itrEnd = maRowManualBreaks.end(); 998 itr != itrEnd; ++itr) 999 pRowFlags->OrValue(*itr, static_int_cast<sal_uInt8>(CR_MANUALBREAK)); 1000 } 1001 1002 if (!maColManualBreaks.empty()) 1003 { 1004 for (set<SCCOL>::const_iterator itr = maColManualBreaks.begin(), itrEnd = maColManualBreaks.end(); 1005 itr != itrEnd; ++itr) 1006 pColFlags[*itr] |= CR_MANUALBREAK; 1007 } 1008 1009 // Hidden flags. 1010 lcl_syncFlags(*mpHiddenCols, *mpHiddenRows, pColFlags, pRowFlags, CR_HIDDEN); 1011 lcl_syncFlags(*mpFilteredCols, *mpFilteredRows, pColFlags, pRowFlags, CR_FILTERED); 1012 } 1013 1014 void ScTable::SetPageSize( const Size& rSize ) 1015 { 1016 if ( rSize.Width() != 0 && rSize.Height() != 0 ) 1017 { 1018 if (aPageSizeTwips != rSize) 1019 InvalidatePageBreaks(); 1020 1021 bPageSizeValid = sal_True; 1022 aPageSizeTwips = rSize; 1023 } 1024 else 1025 bPageSizeValid = sal_False; 1026 } 1027 1028 sal_Bool ScTable::IsProtected() const 1029 { 1030 return pTabProtection.get() && pTabProtection->isProtected(); 1031 } 1032 1033 void ScTable::SetProtection(const ScTableProtection* pProtect) 1034 { 1035 if (pProtect) 1036 pTabProtection.reset(new ScTableProtection(*pProtect)); 1037 else 1038 pTabProtection.reset(NULL); 1039 1040 if (IsStreamValid()) 1041 SetStreamValid(sal_False); 1042 } 1043 1044 ScTableProtection* ScTable::GetProtection() 1045 { 1046 return pTabProtection.get(); 1047 } 1048 1049 Size ScTable::GetPageSize() const 1050 { 1051 if ( bPageSizeValid ) 1052 return aPageSizeTwips; 1053 else 1054 return Size(); // leer 1055 } 1056 1057 void ScTable::SetRepeatArea( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow ) 1058 { 1059 // #i117952# page break calculation uses these values (set from ScPrintFunc), not pRepeatColRange/pRepeatRowRange 1060 if ( nStartCol != nRepeatStartX || nEndCol != nRepeatEndX || nStartRow != nRepeatStartY || nEndRow != nRepeatEndY ) 1061 InvalidatePageBreaks(); 1062 1063 nRepeatStartX = nStartCol; 1064 nRepeatEndX = nEndCol; 1065 nRepeatStartY = nStartRow; 1066 nRepeatEndY = nEndRow; 1067 } 1068 1069 void ScTable::StartListening( const ScAddress& rAddress, SvtListener* pListener ) 1070 { 1071 aCol[rAddress.Col()].StartListening( *pListener, rAddress.Row() ); 1072 } 1073 1074 void ScTable::EndListening( const ScAddress& rAddress, SvtListener* pListener ) 1075 { 1076 aCol[rAddress.Col()].EndListening( *pListener, rAddress.Row() ); 1077 } 1078 1079 void ScTable::SetPageStyle( const String& rName ) 1080 { 1081 if ( aPageStyle != rName ) 1082 { 1083 String aStrNew = rName; 1084 SfxStyleSheetBasePool* pStylePool = pDocument->GetStyleSheetPool(); 1085 SfxStyleSheetBase* pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE ); 1086 1087 if ( !pNewStyle ) 1088 { 1089 aStrNew = ScGlobal::GetRscString(STR_STYLENAME_STANDARD); 1090 pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE ); 1091 } 1092 1093 if ( aPageStyle != aStrNew ) 1094 { 1095 SfxStyleSheetBase* pOldStyle = pStylePool->Find( aPageStyle, SFX_STYLE_FAMILY_PAGE ); 1096 1097 if ( pOldStyle && pNewStyle ) 1098 { 1099 SfxItemSet& rOldSet = pOldStyle->GetItemSet(); 1100 SfxItemSet& rNewSet = pNewStyle->GetItemSet(); 1101 const sal_uInt16 nOldScale = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALE); 1102 const sal_uInt16 nOldScaleToPages = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALETOPAGES); 1103 const sal_uInt16 nNewScale = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALE); 1104 const sal_uInt16 nNewScaleToPages = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALETOPAGES); 1105 1106 if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) ) 1107 InvalidateTextWidth(NULL, NULL, sal_False, sal_False); 1108 } 1109 1110 if ( pNewStyle ) // auch ohne den alten (fuer UpdateStdNames) 1111 aPageStyle = aStrNew; 1112 1113 if (IsStreamValid()) 1114 SetStreamValid(sal_False); 1115 } 1116 } 1117 } 1118 1119 void ScTable::PageStyleModified( const String& rNewName ) 1120 { 1121 aPageStyle = rNewName; 1122 InvalidateTextWidth(NULL, NULL, sal_False, sal_False); // don't know what was in the style before 1123 } 1124 1125 void ScTable::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo, 1126 sal_Bool bNumFormatChanged, sal_Bool bBroadcast ) 1127 { 1128 if ( pAdrFrom && !pAdrTo ) 1129 { 1130 ScBaseCell* pCell = aCol[pAdrFrom->Col()].GetCell( pAdrFrom->Row() ); 1131 if ( pCell ) 1132 { 1133 pCell->SetTextWidth( TEXTWIDTH_DIRTY ); 1134 if ( bNumFormatChanged ) 1135 pCell->SetScriptType( SC_SCRIPTTYPE_UNKNOWN ); 1136 if ( bBroadcast ) 1137 { // nur bei CalcAsShown 1138 switch ( pCell->GetCellType() ) 1139 { 1140 case CELLTYPE_VALUE : 1141 pDocument->Broadcast( SC_HINT_DATACHANGED, 1142 ScAddress( pAdrFrom->Col(), pAdrFrom->Row(), nTab ), 1143 pCell ); 1144 break; 1145 case CELLTYPE_FORMULA : 1146 ((ScFormulaCell*)pCell)->SetDirty(); 1147 break; 1148 default: 1149 { 1150 // added to avoid warnings 1151 } 1152 } 1153 } 1154 } 1155 } 1156 else 1157 { 1158 const SCCOL nColStart = pAdrFrom ? pAdrFrom->Col() : 0; 1159 const SCROW nRowStart = pAdrFrom ? pAdrFrom->Row() : 0; 1160 const SCCOL nColEnd = pAdrTo ? pAdrTo->Col() : MAXCOL; 1161 const SCROW nRowEnd = pAdrTo ? pAdrTo->Row() : MAXROW; 1162 1163 for ( SCCOL nCol=nColStart; nCol<=nColEnd; nCol++ ) 1164 { 1165 ScColumnIterator aIter( &aCol[nCol], nRowStart, nRowEnd ); 1166 ScBaseCell* pCell = NULL; 1167 SCROW nRow = nRowStart; 1168 1169 while ( aIter.Next( nRow, pCell ) ) 1170 { 1171 pCell->SetTextWidth( TEXTWIDTH_DIRTY ); 1172 if ( bNumFormatChanged ) 1173 pCell->SetScriptType( SC_SCRIPTTYPE_UNKNOWN ); 1174 if ( bBroadcast ) 1175 { // nur bei CalcAsShown 1176 switch ( pCell->GetCellType() ) 1177 { 1178 case CELLTYPE_VALUE : 1179 pDocument->Broadcast( SC_HINT_DATACHANGED, 1180 ScAddress( nCol, nRow, nTab ), pCell ); 1181 break; 1182 case CELLTYPE_FORMULA : 1183 ((ScFormulaCell*)pCell)->SetDirty(); 1184 break; 1185 default: 1186 { 1187 // added to avoid warnings 1188 } 1189 } 1190 } 1191 } 1192 } 1193 } 1194 } 1195 1196 1197 1198 1199 1200