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