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