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 // System - Includes ----------------------------------------------------- 28 29 30 31 #include <tools/debug.hxx> 32 #include <limits.h> 33 34 // INCLUDE --------------------------------------------------------------- 35 36 #include "olinetab.hxx" 37 #include "global.hxx" 38 #include "rechead.hxx" 39 #include "address.hxx" 40 #include "table.hxx" 41 42 //------------------------------------------------------------------------ 43 44 ScOutlineEntry::ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, bool bNewHidden ) : 45 nStart ( nNewStart ), 46 nSize ( nNewSize ), 47 bHidden ( bNewHidden ), 48 bVisible( sal_True ) 49 { 50 } 51 52 ScOutlineEntry::ScOutlineEntry( const ScOutlineEntry& rEntry ) : 53 ScDataObject(), 54 nStart ( rEntry.nStart ), 55 nSize ( rEntry.nSize ), 56 bHidden ( rEntry.bHidden ), 57 bVisible( rEntry.bVisible ) 58 { 59 } 60 61 ScDataObject* ScOutlineEntry::Clone() const 62 { 63 return new ScOutlineEntry( *this ); 64 } 65 66 void ScOutlineEntry::Move( SCsCOLROW nDelta ) 67 { 68 SCCOLROW nNewPos = nStart + nDelta; 69 if (nNewPos<0) 70 { 71 DBG_ERROR("OutlineEntry < 0"); 72 nNewPos = 0; 73 } 74 nStart = nNewPos; 75 } 76 77 void ScOutlineEntry::SetSize( SCSIZE nNewSize ) 78 { 79 if (nNewSize>0) 80 nSize = nNewSize; 81 else 82 { 83 DBG_ERROR("ScOutlineEntry Size == 0"); 84 } 85 } 86 87 void ScOutlineEntry::SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize ) 88 { 89 nStart = nNewPos; 90 SetSize( nNewSize ); 91 } 92 93 void ScOutlineEntry::SetHidden( bool bNewHidden ) 94 { 95 bHidden = bNewHidden; 96 } 97 98 void ScOutlineEntry::SetVisible( bool bNewVisible ) 99 { 100 bVisible = bNewVisible; 101 } 102 103 //------------------------------------------------------------------------ 104 105 ScOutlineCollection::ScOutlineCollection() : 106 ScSortedCollection( 4,4,sal_False ) 107 { 108 } 109 110 inline short IntCompare( SCCOLROW nX, SCCOLROW nY ) 111 { 112 if ( nX==nY ) return 0; 113 else if ( nX<nY ) return -1; 114 else return 1; 115 } 116 117 short ScOutlineCollection::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const 118 { 119 return IntCompare( ((ScOutlineEntry*)pKey1)->GetStart(), 120 ((ScOutlineEntry*)pKey2)->GetStart() ); 121 } 122 123 sal_uInt16 ScOutlineCollection::FindStart( SCCOLROW nMinStart ) 124 { 125 //! binaer suchen ? 126 127 sal_uInt16 nPos = 0; 128 sal_uInt16 nLocalCount = GetCount(); 129 while ( (nPos<nLocalCount) ? (((ScOutlineEntry*)At(nPos))->GetStart() < nMinStart) : sal_False ) 130 ++nPos; 131 132 return nPos; 133 } 134 135 //------------------------------------------------------------------------ 136 137 ScOutlineArray::ScOutlineArray() : 138 nDepth( 0 ) 139 { 140 } 141 142 ScOutlineArray::ScOutlineArray( const ScOutlineArray& rArray ) : 143 nDepth( rArray.nDepth ) 144 { 145 for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++) 146 { 147 sal_uInt16 nCount = rArray.aCollections[nLevel].GetCount(); 148 for (sal_uInt16 nEntry=0; nEntry<nCount; nEntry++) 149 { 150 ScOutlineEntry* pEntry = (ScOutlineEntry*) rArray.aCollections[nLevel].At(nEntry); 151 aCollections[nLevel].Insert( new ScOutlineEntry( *pEntry ) ); 152 } 153 } 154 } 155 156 void ScOutlineArray::FindEntry( SCCOLROW nSearchPos, sal_uInt16& rFindLevel, sal_uInt16& rFindIndex, 157 sal_uInt16 nMaxLevel ) 158 { 159 rFindLevel = rFindIndex = 0; 160 161 if (nMaxLevel > nDepth) 162 nMaxLevel = nDepth; 163 164 for (sal_uInt16 nLevel=0; nLevel<nMaxLevel; nLevel++) //! rueckwaerts suchen ? 165 { 166 ScOutlineCollection* pCollect = &aCollections[nLevel]; 167 sal_uInt16 nCount = pCollect->GetCount(); 168 for (sal_uInt16 i=0; i<nCount; i++) 169 { 170 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); 171 if ( pEntry->GetStart() <= nSearchPos && pEntry->GetEnd() >= nSearchPos ) 172 { 173 rFindLevel = nLevel + 1; // naechster Level (zum Einfuegen) 174 rFindIndex = i; 175 } 176 } 177 } 178 } 179 180 sal_Bool ScOutlineArray::Insert( SCCOLROW nStartCol, SCCOLROW nEndCol, sal_Bool& rSizeChanged, 181 sal_Bool bHidden, sal_Bool bVisible ) 182 { 183 rSizeChanged = sal_False; 184 185 sal_uInt16 nStartLevel; 186 sal_uInt16 nStartIndex; 187 sal_uInt16 nEndLevel; 188 sal_uInt16 nEndIndex; 189 sal_Bool bFound = sal_False; 190 191 sal_Bool bCont; 192 sal_uInt16 nFindMax; 193 FindEntry( nStartCol, nStartLevel, nStartIndex ); // nLevel = neuer Level (alter+1) !!! 194 FindEntry( nEndCol, nEndLevel, nEndIndex ); 195 nFindMax = Max(nStartLevel,nEndLevel); 196 do 197 { 198 bCont = sal_False; 199 200 if ( nStartLevel == nEndLevel && nStartIndex == nEndIndex && nStartLevel < SC_OL_MAXDEPTH ) 201 bFound = sal_True; 202 203 if (!bFound) 204 { 205 if (nFindMax>0) 206 { 207 --nFindMax; 208 if (nStartLevel) 209 if ( ((ScOutlineEntry*)aCollections[nStartLevel-1].At(nStartIndex))-> 210 GetStart() == nStartCol ) 211 FindEntry( nStartCol, nStartLevel, nStartIndex, nFindMax ); 212 if (nEndLevel) 213 if ( ((ScOutlineEntry*)aCollections[nEndLevel-1].At(nEndIndex))-> 214 GetEnd() == nEndCol ) 215 FindEntry( nEndCol, nEndLevel, nEndIndex, nFindMax ); 216 bCont = sal_True; 217 } 218 } 219 } 220 while ( !bFound && bCont ); 221 222 if (!bFound) 223 return sal_False; 224 225 sal_uInt16 nLevel = nStartLevel; 226 227 // untere verschieben 228 229 sal_Bool bNeedSize = sal_False; 230 for ( short nMoveLevel = nDepth-1; nMoveLevel >= (short) nLevel; nMoveLevel-- ) 231 { 232 sal_uInt16 nCount = aCollections[nMoveLevel].GetCount(); 233 sal_Bool bMoved = sal_False; 234 for ( sal_uInt16 i=0; i<nCount; i += bMoved ? 0 : 1 ) 235 { 236 ScOutlineEntry* pEntry = (ScOutlineEntry*) aCollections[nMoveLevel].At(i); 237 SCCOLROW nEntryStart = pEntry->GetStart(); 238 if ( nEntryStart >= nStartCol && nEntryStart <= nEndCol ) 239 { 240 if (nMoveLevel >= SC_OL_MAXDEPTH - 1) 241 { 242 rSizeChanged = sal_False; // kein Platz 243 return sal_False; 244 } 245 aCollections[nMoveLevel+1].Insert( new ScOutlineEntry( *pEntry ) ); 246 aCollections[nMoveLevel].AtFree( i ); 247 nCount = aCollections[nMoveLevel].GetCount(); 248 bMoved = sal_True; 249 if (nMoveLevel == (short) nDepth - 1) 250 bNeedSize = sal_True; 251 } 252 else 253 bMoved = sal_False; 254 } 255 } 256 257 if (bNeedSize) 258 { 259 ++nDepth; 260 rSizeChanged = sal_True; 261 } 262 263 if (nDepth <= nLevel) 264 { 265 nDepth = nLevel+1; 266 rSizeChanged = sal_True; 267 } 268 269 /* nicht zusammenfassen! 270 271 // zusammenfassen 272 273 sal_uInt16 nCount = aCollections[nLevel].GetCount(); 274 sal_uInt16 nIndex; 275 bFound = sal_False; 276 for ( nIndex=0; nIndex<nCount && !bFound; nIndex++ ) 277 { 278 if ( ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetEnd() + 1 == nStartCol ) 279 { 280 nStartCol = ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetStart(); 281 aCollections[nLevel].AtFree(nIndex); 282 nCount = aCollections[nLevel].GetCount(); // Daten geaendert 283 bFound = sal_True; 284 } 285 } 286 287 bFound = sal_False; 288 for ( nIndex=0; nIndex<nCount && !bFound; nIndex++ ) 289 { 290 if ( ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetStart() == nEndCol + 1 ) 291 { 292 nEndCol = ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetEnd(); 293 aCollections[nLevel].AtFree(nIndex); 294 bFound = sal_True; 295 } 296 } 297 */ 298 ScOutlineEntry* pNewEntry = new ScOutlineEntry( nStartCol, nEndCol+1-nStartCol, bHidden ); 299 pNewEntry->SetVisible( bVisible ); 300 aCollections[nLevel].Insert( pNewEntry ); 301 302 return sal_True; 303 } 304 305 sal_Bool ScOutlineArray::FindTouchedLevel( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_uInt16& rFindLevel ) const 306 { 307 sal_Bool bFound = sal_False; 308 rFindLevel = 0; 309 310 for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++) 311 { 312 const ScOutlineCollection* pCollect = &aCollections[nLevel]; 313 sal_uInt16 nCount = pCollect->GetCount(); 314 for (sal_uInt16 i=0; i<nCount; i++) 315 { 316 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); 317 SCCOLROW nStart = pEntry->GetStart(); 318 SCCOLROW nEnd = pEntry->GetEnd(); 319 320 if ( ( nBlockStart>=nStart && nBlockStart<=nEnd ) || 321 ( nBlockEnd >=nStart && nBlockEnd <=nEnd ) ) 322 { 323 rFindLevel = nLevel; // wirklicher Level 324 bFound = sal_True; 325 } 326 } 327 } 328 329 return bFound; 330 } 331 332 void ScOutlineArray::RemoveSub( SCCOLROW nStartPos, SCCOLROW nEndPos, sal_uInt16 nLevel ) 333 { 334 if ( nLevel >= nDepth ) 335 return; 336 ScOutlineCollection* pCollect = &aCollections[nLevel]; 337 sal_uInt16 nCount = pCollect->GetCount(); 338 sal_Bool bFound = sal_False; 339 for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) ) 340 { 341 bFound = sal_False; 342 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); 343 SCCOLROW nStart = pEntry->GetStart(); 344 SCCOLROW nEnd = pEntry->GetEnd(); 345 346 if ( nStart>=nStartPos && nEnd<=nEndPos ) 347 { 348 RemoveSub( nStart, nEnd, nLevel+1 ); 349 pCollect->AtFree(i); 350 nCount = pCollect->GetCount(); 351 bFound = sal_True; 352 } 353 } 354 } 355 356 void ScOutlineArray::PromoteSub( SCCOLROW nStartPos, SCCOLROW nEndPos, sal_uInt16 nStartLevel ) 357 { 358 if (nStartLevel==0) 359 { 360 DBG_ERROR("PromoteSub mit Level 0"); 361 return; 362 } 363 364 for (sal_uInt16 nLevel = nStartLevel; nLevel < nDepth; nLevel++) 365 { 366 ScOutlineCollection* pCollect = &aCollections[nLevel]; 367 sal_uInt16 nCount = pCollect->GetCount(); 368 sal_Bool bFound = sal_False; 369 for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) ) 370 { 371 bFound = sal_False; 372 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); 373 SCCOLROW nStart = pEntry->GetStart(); 374 SCCOLROW nEnd = pEntry->GetEnd(); 375 376 if ( nStart>=nStartPos && nEnd<=nEndPos ) 377 { 378 aCollections[nLevel-1].Insert( new ScOutlineEntry( *pEntry ) ); 379 pCollect->AtFree(i); 380 nCount = pCollect->GetCount(); 381 bFound = sal_True; 382 } 383 } 384 } 385 } 386 387 sal_Bool ScOutlineArray::DecDepth() // nDepth auf leere Levels anpassen 388 { 389 sal_Bool bChanged = sal_False; 390 sal_Bool bCont; 391 do 392 { 393 bCont = sal_False; 394 if (nDepth) 395 if (aCollections[nDepth-1].GetCount() == 0) 396 { 397 --nDepth; 398 bChanged = sal_True; 399 bCont = sal_True; 400 } 401 } 402 while (bCont); 403 return bChanged; 404 } 405 406 sal_Bool ScOutlineArray::Remove( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_Bool& rSizeChanged ) 407 { 408 sal_uInt16 nLevel; 409 FindTouchedLevel( nBlockStart, nBlockEnd, nLevel ); 410 411 ScOutlineCollection* pCollect = &aCollections[nLevel]; 412 sal_uInt16 nCount = pCollect->GetCount(); 413 sal_Bool bFound = sal_False; 414 sal_Bool bAny = sal_False; 415 for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) ) 416 { 417 bFound = sal_False; 418 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); 419 SCCOLROW nStart = pEntry->GetStart(); 420 SCCOLROW nEnd = pEntry->GetEnd(); 421 422 if ( nBlockStart<=nEnd && nBlockEnd>=nStart ) 423 { 424 // RemoveSub( nStart, nEnd, nLevel+1 ); 425 pCollect->AtFree(i); 426 PromoteSub( nStart, nEnd, nLevel+1 ); 427 nCount = pCollect->GetCount(); 428 i = pCollect->FindStart( nEnd+1 ); 429 bFound = sal_True; 430 bAny = sal_True; 431 } 432 } 433 434 if (bAny) // Depth anpassen 435 if (DecDepth()) 436 rSizeChanged = sal_True; 437 438 return bAny; 439 } 440 441 ScOutlineEntry* ScOutlineArray::GetEntry( sal_uInt16 nLevel, sal_uInt16 nIndex ) const 442 { 443 return (ScOutlineEntry*)((nLevel < nDepth) ? aCollections[nLevel].At(nIndex) : NULL); 444 } 445 446 sal_uInt16 ScOutlineArray::GetCount( sal_uInt16 nLevel ) const 447 { 448 return (nLevel < nDepth) ? aCollections[nLevel].GetCount() : 0; 449 } 450 451 ScOutlineEntry* ScOutlineArray::GetEntryByPos( sal_uInt16 nLevel, SCCOLROW nPos ) const 452 { 453 sal_uInt16 nCount = GetCount( nLevel ); 454 ScOutlineEntry* pEntry; 455 456 for (sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++) 457 { 458 pEntry = GetEntry( nLevel, nIndex ); 459 if ((pEntry->GetStart() <= nPos) && (nPos <= pEntry->GetEnd())) 460 return pEntry; 461 } 462 return NULL; 463 } 464 465 sal_Bool ScOutlineArray::GetEntryIndex( sal_uInt16 nLevel, SCCOLROW nPos, sal_uInt16& rnIndex ) const 466 { 467 // found entry contains passed position 468 sal_uInt16 nCount = GetCount( nLevel ); 469 for ( rnIndex = 0; rnIndex < nCount; ++rnIndex ) 470 { 471 const ScOutlineEntry* pEntry = GetEntry( nLevel, rnIndex ); 472 if ( (pEntry->GetStart() <= nPos) && (nPos <= pEntry->GetEnd()) ) 473 return sal_True; 474 } 475 return sal_False; 476 } 477 478 sal_Bool ScOutlineArray::GetEntryIndexInRange( 479 sal_uInt16 nLevel, SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_uInt16& rnIndex ) const 480 { 481 // found entry will be completely inside of passed range 482 sal_uInt16 nCount = GetCount( nLevel ); 483 for ( rnIndex = 0; rnIndex < nCount; ++rnIndex ) 484 { 485 const ScOutlineEntry* pEntry = GetEntry( nLevel, rnIndex ); 486 if ( (nBlockStart <= pEntry->GetStart()) && (pEntry->GetEnd() <= nBlockEnd) ) 487 return sal_True; 488 } 489 return sal_False; 490 } 491 492 void ScOutlineArray::SetVisibleBelow( sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bValue, sal_Bool bSkipHidden ) 493 { 494 ScOutlineEntry* pEntry = GetEntry( nLevel, nEntry ); 495 if( pEntry ) 496 { 497 SCCOLROW nStart = pEntry->GetStart(); 498 SCCOLROW nEnd = pEntry->GetEnd(); 499 500 for (sal_uInt16 nSubLevel=nLevel+1; nSubLevel<nDepth; nSubLevel++) 501 { 502 sal_uInt16 i = 0; 503 pEntry = (ScOutlineEntry*) aCollections[nSubLevel].At(i); 504 while (pEntry) 505 { 506 if (pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd) 507 { 508 pEntry->SetVisible(bValue); 509 510 if (bSkipHidden) 511 if (!pEntry->IsHidden()) 512 SetVisibleBelow( nSubLevel, i, bValue, sal_True ); 513 } 514 515 ++i; 516 pEntry = (ScOutlineEntry*) aCollections[nSubLevel].At(i); 517 } 518 519 if (bSkipHidden) 520 nSubLevel = nDepth; // Abbruch 521 } 522 } 523 } 524 525 void ScOutlineArray::GetRange( SCCOLROW& rStart, SCCOLROW& rEnd ) const 526 { 527 sal_uInt16 nCount = aCollections[0].GetCount(); 528 if (nCount) 529 { 530 rStart = ((ScOutlineEntry*) aCollections[0].At(0))->GetStart(); 531 rEnd = ((ScOutlineEntry*) aCollections[0].At(nCount-1))->GetEnd(); 532 } 533 else 534 rStart = rEnd = 0; 535 } 536 537 void ScOutlineArray::ExtendBlock( sal_uInt16 nLevel, SCCOLROW& rBlkStart, SCCOLROW& rBlkEnd ) 538 { 539 sal_uInt16 nCount; 540 SCCOLROW nStart; 541 SCCOLROW nEnd; 542 sal_uInt16 i; 543 ScOutlineEntry* pEntry; 544 545 nCount = GetCount(nLevel); 546 for ( i=0; i<nCount; i++ ) 547 { 548 pEntry = (ScOutlineEntry*) aCollections[nLevel].At(i); 549 nStart = pEntry->GetStart(); 550 nEnd = pEntry->GetEnd(); 551 552 if ( rBlkStart<=nEnd && rBlkEnd>=nStart ) 553 { 554 if (nStart<rBlkStart) rBlkStart = nStart; 555 if (nEnd>rBlkEnd) rBlkEnd = nEnd; 556 } 557 } 558 } 559 560 sal_Bool ScOutlineArray::TestInsertSpace( SCSIZE nSize, SCCOLROW nMaxVal ) const 561 { 562 sal_uInt16 nCount = aCollections[0].GetCount(); 563 if (nCount) 564 { 565 SCCOLROW nEnd = ((ScOutlineEntry*) aCollections[0].At(nCount-1))->GetEnd(); 566 return ( sal::static_int_cast<SCCOLROW>(nEnd+nSize) <= nMaxVal ); 567 } 568 569 return sal_True; 570 } 571 572 void ScOutlineArray::InsertSpace( SCCOLROW nStartPos, SCSIZE nSize ) 573 { 574 ScSubOutlineIterator aIter( this ); 575 ScOutlineEntry* pEntry; 576 while((pEntry=aIter.GetNext())!=NULL) 577 { 578 if ( pEntry->GetStart() >= nStartPos ) 579 pEntry->Move(static_cast<SCsCOLROW>(nSize)); 580 else 581 { 582 SCCOLROW nEnd = pEntry->GetEnd(); 583 // immer erweitern, wenn innerhalb der Gruppe eingefuegt 584 // beim Einfuegen am Ende nur, wenn die Gruppe nicht ausgeblendet ist 585 if ( nEnd >= nStartPos || ( nEnd+1 >= nStartPos && !pEntry->IsHidden() ) ) 586 { 587 SCSIZE nEntrySize = pEntry->GetSize(); 588 nEntrySize += nSize; 589 pEntry->SetSize( nEntrySize ); 590 } 591 } 592 } 593 } 594 595 sal_Bool ScOutlineArray::DeleteSpace( SCCOLROW nStartPos, SCSIZE nSize ) 596 { 597 SCCOLROW nEndPos = nStartPos + nSize - 1; 598 sal_Bool bNeedSave = sal_False; // Original fuer Undo benoetigt? 599 sal_Bool bChanged = sal_False; // fuer Test auf Level 600 601 ScSubOutlineIterator aIter( this ); 602 ScOutlineEntry* pEntry; 603 while((pEntry=aIter.GetNext())!=NULL) 604 { 605 SCCOLROW nEntryStart = pEntry->GetStart(); 606 SCCOLROW nEntryEnd = pEntry->GetEnd(); 607 SCSIZE nEntrySize = pEntry->GetSize(); 608 609 if ( nEntryEnd >= nStartPos ) 610 { 611 if ( nEntryStart > nEndPos ) // rechts 612 pEntry->Move(-(static_cast<SCsCOLROW>(nSize))); 613 else if ( nEntryStart < nStartPos && nEntryEnd >= nEndPos ) // aussen 614 pEntry->SetSize( nEntrySize-nSize ); 615 else 616 { 617 bNeedSave = sal_True; 618 if ( nEntryStart >= nStartPos && nEntryEnd <= nEndPos ) // innen 619 { 620 aIter.DeleteLast(); 621 bChanged = sal_True; 622 } 623 else if ( nEntryStart >= nStartPos ) // rechts ueber 624 pEntry->SetPosSize( nStartPos, static_cast<SCSIZE>(nEntryEnd-nEndPos) ); 625 else // links ueber 626 pEntry->SetSize( static_cast<SCSIZE>(nStartPos-nEntryStart) ); 627 } 628 } 629 } 630 631 if (bChanged) 632 DecDepth(); 633 634 return bNeedSave; 635 } 636 637 bool ScOutlineArray::ManualAction( SCCOLROW nStartPos, SCCOLROW nEndPos, bool bShow, ScTable& rTable, bool bCol ) 638 { 639 bool bModified = false; 640 ScSubOutlineIterator aIter( this ); 641 ScOutlineEntry* pEntry; 642 while((pEntry=aIter.GetNext())!=NULL) 643 { 644 SCCOLROW nEntryStart = pEntry->GetStart(); 645 SCCOLROW nEntryEnd = pEntry->GetEnd(); 646 647 if (nEntryEnd>=nStartPos && nEntryStart<=nEndPos) 648 { 649 if ( pEntry->IsHidden() == bShow ) 650 { 651 // #i12341# hide if all columns/rows are hidden, show if at least one 652 // is visible 653 SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, bCol); 654 bool bAllHidden = (nEntryEnd <= nEnd && nEnd < 655 ::std::numeric_limits<SCCOLROW>::max()); 656 657 bool bToggle = ( bShow != bAllHidden ); 658 if ( bToggle ) 659 { 660 pEntry->SetHidden( !bShow ); 661 SetVisibleBelow( aIter.LastLevel(), aIter.LastEntry(), bShow, bShow ); 662 bModified = true; 663 } 664 } 665 } 666 } 667 return bModified; 668 } 669 670 void ScOutlineArray::RemoveAll() 671 { 672 for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++) 673 aCollections[nLevel].FreeAll(); 674 675 nDepth = 0; 676 } 677 678 //------------------------------------------------------------------------ 679 680 ScOutlineTable::ScOutlineTable() 681 { 682 } 683 684 ScOutlineTable::ScOutlineTable( const ScOutlineTable& rOutline ) : 685 aColOutline( rOutline.aColOutline ), 686 aRowOutline( rOutline.aRowOutline ) 687 { 688 } 689 690 sal_Bool ScOutlineTable::TestInsertCol( SCSIZE nSize ) 691 { 692 return aColOutline.TestInsertSpace( nSize, MAXCOL ); 693 } 694 695 void ScOutlineTable::InsertCol( SCCOL nStartCol, SCSIZE nSize ) 696 { 697 aColOutline.InsertSpace( nStartCol, nSize ); 698 } 699 700 sal_Bool ScOutlineTable::DeleteCol( SCCOL nStartCol, SCSIZE nSize ) 701 { 702 return aColOutline.DeleteSpace( nStartCol, nSize ); 703 } 704 705 sal_Bool ScOutlineTable::TestInsertRow( SCSIZE nSize ) 706 { 707 return aRowOutline.TestInsertSpace( nSize, MAXROW ); 708 } 709 710 void ScOutlineTable::InsertRow( SCROW nStartRow, SCSIZE nSize ) 711 { 712 aRowOutline.InsertSpace( nStartRow, nSize ); 713 } 714 715 sal_Bool ScOutlineTable::DeleteRow( SCROW nStartRow, SCSIZE nSize ) 716 { 717 return aRowOutline.DeleteSpace( nStartRow, nSize ); 718 } 719 720 //------------------------------------------------------------------------ 721 722 ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray ) : 723 pArray( pOutlineArray ), 724 nStart( 0 ), 725 nEnd( SCCOLROW_MAX ), // alle durchgehen 726 nSubLevel( 0 ), 727 nSubEntry( 0 ) 728 { 729 nDepth = pArray->nDepth; 730 } 731 732 ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray, 733 sal_uInt16 nLevel, sal_uInt16 nEntry ) : 734 pArray( pOutlineArray ) 735 { 736 ScOutlineEntry* pEntry = (ScOutlineEntry*) pArray->aCollections[nLevel].At(nEntry); 737 nStart = pEntry->GetStart(); 738 nEnd = pEntry->GetEnd(); 739 nSubLevel = nLevel + 1; 740 nSubEntry = 0; 741 nDepth = pArray->nDepth; 742 } 743 744 ScOutlineEntry* ScSubOutlineIterator::GetNext() 745 { 746 ScOutlineEntry* pEntry; 747 sal_Bool bFound = sal_False; 748 do 749 { 750 if (nSubLevel >= nDepth) 751 return NULL; 752 753 pEntry = (ScOutlineEntry*) pArray->aCollections[nSubLevel].At(nSubEntry); 754 if (!pEntry) 755 { 756 nSubEntry = 0; 757 ++nSubLevel; 758 } 759 else 760 { 761 if ( pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd ) 762 bFound = sal_True; 763 ++nSubEntry; 764 } 765 } 766 while (!bFound); 767 return pEntry; // nSubLevel gueltig, wenn pEntry != 0 768 } 769 770 sal_uInt16 ScSubOutlineIterator::LastLevel() const 771 { 772 return nSubLevel; 773 } 774 775 sal_uInt16 ScSubOutlineIterator::LastEntry() const 776 { 777 if (nSubEntry == 0) 778 { 779 DBG_ERROR("ScSubOutlineIterator::LastEntry vor GetNext"); 780 return 0; 781 } 782 return nSubEntry-1; 783 } 784 785 void ScSubOutlineIterator::DeleteLast() 786 { 787 if (nSubLevel >= nDepth) 788 { 789 DBG_ERROR("ScSubOutlineIterator::DeleteLast nach Ende"); 790 return; 791 } 792 if (nSubEntry == 0) 793 { 794 DBG_ERROR("ScSubOutlineIterator::DeleteLast vor GetNext"); 795 return; 796 } 797 798 --nSubEntry; 799 pArray->aCollections[nSubLevel].AtFree(nSubEntry); 800 } 801 802 803