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