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_sw.hxx" 30 31 32 #include <hintids.hxx> 33 #include <tools/shl.hxx> 34 #include <svl/itemiter.hxx> 35 #include <sfx2/app.hxx> 36 #include <editeng/colritem.hxx> 37 #include <editeng/udlnitem.hxx> 38 #include <editeng/crsditem.hxx> 39 #include <swmodule.hxx> 40 #include <doc.hxx> 41 #include <IDocumentUndoRedo.hxx> 42 #include <docary.hxx> 43 #include <ndtxt.hxx> 44 #include <redline.hxx> 45 #include <swundo.hxx> 46 #include <UndoCore.hxx> 47 #include <UndoRedline.hxx> 48 #include <hints.hxx> 49 #include <pamtyp.hxx> 50 #include <poolfmt.hxx> 51 #include <viewsh.hxx> 52 #include <rootfrm.hxx> 53 54 #include <comcore.hrc> 55 56 using namespace com::sun::star; 57 58 TYPEINIT1(SwRedlineHint, SfxHint); 59 60 #ifndef DBG_UTIL 61 62 #define _CHECK_REDLINE( pDoc ) 63 #define _DEBUG_REDLINE( pDoc ) 64 65 #else 66 67 #define _ERROR_PREFIX "redline table corrupted: " 68 69 // helper function for lcl_CheckRedline 70 // 1. make sure that pPos->nContent points into pPos->nNode 71 // (or into the 'special' no-content-node-IndexReg) 72 // 2. check that position is valid and doesn't point behind text 73 void lcl_CheckPosition( const SwPosition* pPos ) 74 { 75 SwPosition aComparePos( *pPos ); 76 aComparePos.nContent.Assign( 77 aComparePos.nNode.GetNode().GetCntntNode(), 0 ); 78 DBG_ASSERT( pPos->nContent.GetIdxReg() == 79 aComparePos.nContent.GetIdxReg(), 80 _ERROR_PREFIX "illegal position" ); 81 82 SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode(); 83 if( pTxtNode == NULL ) 84 { 85 DBG_ASSERT( pPos->nContent == 0, 86 _ERROR_PREFIX "non-text-node with content" ); 87 } 88 else 89 { 90 DBG_ASSERT( pPos->nContent >= 0 && 91 pPos->nContent <= pTxtNode->Len(), 92 _ERROR_PREFIX "index behind text" ); 93 } 94 } 95 96 void lcl_CheckPam( const SwPaM* pPam ) 97 { 98 DBG_ASSERT( pPam != NULL, _ERROR_PREFIX "illegal argument" ); 99 lcl_CheckPosition( pPam->GetPoint() ); 100 lcl_CheckPosition( pPam->GetMark() ); 101 } 102 103 // check validity of the redline table. Checks redline bounds, and make 104 // sure the redlines are sorted and non-overlapping. 105 void lcl_CheckRedline( const SwDoc* pDoc ) 106 { 107 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 108 109 // verify valid redline positions 110 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i ) 111 lcl_CheckPam( rTbl[ i ] ); 112 113 for( sal_uInt16 j = 0; j < rTbl.Count(); ++j ) 114 { 115 // check for empty redlines 116 DBG_ASSERT( ( *(rTbl[j]->GetPoint()) != *(rTbl[j]->GetMark()) ) || 117 ( rTbl[j]->GetContentIdx() != NULL ), 118 _ERROR_PREFIX "empty redline" ); 119 } 120 121 // verify proper redline sorting 122 for( sal_uInt16 n = 1; n < rTbl.Count(); ++n ) 123 { 124 const SwRedline* pPrev = rTbl[ n-1 ]; 125 const SwRedline* pCurrent = rTbl[ n ]; 126 127 // check redline sorting 128 DBG_ASSERT( *pPrev->Start() <= *pCurrent->Start(), 129 _ERROR_PREFIX "not sorted correctly" ); 130 131 // check for overlapping redlines 132 DBG_ASSERT( *pPrev->End() <= *pCurrent->Start(), 133 _ERROR_PREFIX "overlapping redlines" ); 134 } 135 } 136 137 #define _CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc ); 138 139 void lcl_DebugRedline( const SwDoc* pDoc ) 140 { 141 static sal_uInt16 nWatch = 0; 142 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 143 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 144 { 145 sal_uInt16 nDummy = 0; 146 const SwRedline* pCurrent = rTbl[ n ]; 147 const SwRedline* pNext = n+1 < rTbl.Count() ? rTbl[ n+1 ] : 0; 148 if( pCurrent == pNext ) 149 ++nDummy; 150 if( n == nWatch ) 151 ++nDummy; // Possible debugger breakpoint 152 } 153 } 154 155 #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc ); 156 157 #endif 158 159 SV_IMPL_OP_PTRARR_SORT( _SwRedlineTbl, SwRedlinePtr ) 160 161 RedlineMode_t SwDoc::GetRedlineMode() const 162 { 163 return eRedlineMode; 164 } 165 166 void SwDoc::SetRedlineMode( RedlineMode_t eMode ) 167 { 168 if( eRedlineMode != eMode ) 169 { 170 if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) 171 || 0 == (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) ) 172 { 173 bool bSaveInXMLImportFlag = IsInXMLImport(); 174 SetInXMLImport( false ); 175 // und dann alles verstecken, anzeigen 176 void (SwRedline::*pFnc)( sal_uInt16 ) = 0; 177 178 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode ) 179 { 180 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE : 181 pFnc = &SwRedline::Show; 182 break; 183 case nsRedlineMode_t::REDLINE_SHOW_INSERT: 184 pFnc = &SwRedline::Hide; 185 break; 186 case nsRedlineMode_t::REDLINE_SHOW_DELETE: 187 pFnc = &SwRedline::ShowOriginal; 188 break; 189 190 default: 191 pFnc = &SwRedline::Hide; 192 eMode = (RedlineMode_t)(eMode | nsRedlineMode_t::REDLINE_SHOW_INSERT); 193 break; 194 } 195 196 _CHECK_REDLINE( this ) 197 198 if( pFnc ) 199 for( sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop ) 200 for( sal_uInt16 i = 0; i < pRedlineTbl->Count(); ++i ) 201 ((*pRedlineTbl)[ i ]->*pFnc)( nLoop ); 202 _CHECK_REDLINE( this ) 203 SetInXMLImport( bSaveInXMLImportFlag ); 204 } 205 eRedlineMode = eMode; 206 SetModified(); 207 } 208 } 209 210 bool SwDoc::IsRedlineOn() const 211 { 212 return IDocumentRedlineAccess::IsRedlineOn(eRedlineMode); 213 } 214 215 bool SwDoc::IsIgnoreRedline() const 216 { 217 return (nsRedlineMode_t::REDLINE_IGNORE & eRedlineMode); 218 } 219 220 void SwDoc::SetRedlineMode_intern(RedlineMode_t eMode) 221 { 222 eRedlineMode = eMode; 223 } 224 225 const SwRedlineTbl& SwDoc::GetRedlineTbl() const 226 { 227 return *pRedlineTbl; 228 } 229 230 bool SwDoc::IsRedlineMove() const 231 { 232 return mbIsRedlineMove; 233 } 234 235 void SwDoc::SetRedlineMove(bool bFlag) 236 { 237 mbIsRedlineMove = bFlag; 238 } 239 240 const uno::Sequence <sal_Int8>& SwDoc::GetRedlinePassword() const 241 { 242 return aRedlinePasswd; 243 } 244 245 inline bool IsPrevPos( const SwPosition rPos1, const SwPosition rPos2 ) 246 { 247 const SwCntntNode* pCNd; 248 return 0 == rPos2.nContent.GetIndex() && 249 rPos2.nNode.GetIndex() - 1 == rPos1.nNode.GetIndex() && 250 0 != ( pCNd = rPos1.nNode.GetNode().GetCntntNode() ) 251 ? rPos1.nContent.GetIndex() == pCNd->Len() 252 : false; 253 } 254 255 #ifdef DEBUG 256 bool CheckPosition( const SwPosition* pStt, const SwPosition* pEnd ) 257 { 258 int nError = 0; 259 SwNode* pSttNode = &pStt->nNode.GetNode(); 260 SwNode* pEndNode = &pEnd->nNode.GetNode(); 261 SwNode* pSttTab = pSttNode->StartOfSectionNode()->FindTableNode(); 262 SwNode* pEndTab = pEndNode->StartOfSectionNode()->FindTableNode(); 263 SwNode* pSttStart = pSttNode; 264 while( pSttStart && (!pSttStart->IsStartNode() || pSttStart->IsSectionNode() || 265 pSttStart->IsTableNode() ) ) 266 pSttStart = pSttStart->StartOfSectionNode(); 267 SwNode* pEndStart = pEndNode; 268 while( pEndStart && (!pEndStart->IsStartNode() || pEndStart->IsSectionNode() || 269 pEndStart->IsTableNode() ) ) 270 pEndStart = pEndStart->StartOfSectionNode(); 271 if( pSttTab != pEndTab ) 272 nError = 1; 273 if( !pSttTab && pSttStart != pEndStart ) 274 nError |= 2; 275 if( nError ) 276 nError += 10; 277 return nError != 0; 278 } 279 #endif 280 281 /* 282 283 Text heisst, nicht von Redline "verseuchter" Text. 284 285 Verhalten von Insert-Redline: 286 - im Text - Redline Object einfuegen 287 - im InsertRedline (eigenes) - ignorieren, bestehendes wird 288 aufgespannt 289 - im InsertRedline (andere) - Insert Redline aufsplitten 290 Redline Object einfuegen 291 - in DeleteRedline - Delete Redline aufsplitten oder 292 am Ende/Anfang verschieben 293 294 Verhalten von Delete-Redline: 295 - im Text - Redline Object einfuegen 296 - im DeleteRedline (eigenes/andere) - ignorieren 297 - im InsertRedline (eigenes) - ignorieren, Zeichen aber loeschen 298 - im InsertRedline (andere) - Insert Redline aufsplitten 299 Redline Object einfuegen 300 - Ueberlappung von Text und - Text in eigenen Insert loeschen, 301 eigenem Insert im andereren Text aufspannen (bis 302 zum Insert! 303 - Ueberlappung von Text und - Redline Object einfuegen, der 304 anderem Insert andere Insert wird vom Delete 305 ueberlappt 306 */ 307 308 bool SwDoc::AppendRedline( SwRedline* pNewRedl, bool bCallDelete ) 309 { 310 #if 0 311 // #i93179# disabled: ASSERT in ~SwIndexReg #ifdef DBG_UTIL 312 SwRedline aCopy( *pNewRedl ); 313 #endif 314 bool bError = true; 315 _CHECK_REDLINE( this ) 316 317 if( IsRedlineOn() && !IsShowOriginal( eRedlineMode ) && 318 pNewRedl->GetAuthorString().Len() ) 319 { 320 pNewRedl->InvalidateRange(); 321 322 if( mbIsAutoFmtRedline ) 323 { 324 pNewRedl->SetAutoFmtFlag(); 325 if( pAutoFmtRedlnComment && pAutoFmtRedlnComment->Len() ) 326 { 327 pNewRedl->SetComment( *pAutoFmtRedlnComment ); 328 pNewRedl->SetSeqNo( nAutoFmtRedlnCommentNo ); 329 } 330 } 331 332 SwPosition* pStt = pNewRedl->Start(), 333 * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark() 334 : pNewRedl->GetPoint(); 335 { 336 SwTxtNode* pTxtNode = pStt->nNode.GetNode().GetTxtNode(); 337 if( pTxtNode == NULL ) 338 { 339 if( pStt->nContent > 0 ) 340 { 341 DBG_ASSERT( false, "Redline start: non-text-node with content" ); 342 pStt->nContent = 0; 343 } 344 } 345 else 346 { 347 if( pStt->nContent > pTxtNode->Len() ) 348 { 349 DBG_ASSERT( false, "Redline start: index behind text" ); 350 pStt->nContent = pTxtNode->Len(); 351 } 352 } 353 pTxtNode = pEnd->nNode.GetNode().GetTxtNode(); 354 if( pTxtNode == NULL ) 355 { 356 if( pEnd->nContent > 0 ) 357 { 358 DBG_ASSERT( false, "Redline end: non-text-node with content" ); 359 pEnd->nContent = 0; 360 } 361 } 362 else 363 { 364 if( pEnd->nContent > pTxtNode->Len() ) 365 { 366 DBG_ASSERT( false, "Redline end: index behind text" ); 367 pEnd->nContent = pTxtNode->Len(); 368 } 369 } 370 } 371 if( ( *pStt == *pEnd ) && 372 ( pNewRedl->GetContentIdx() == NULL ) ) 373 { // Do not insert empty redlines 374 delete pNewRedl; 375 return sal_False; 376 } 377 sal_Bool bCompress = sal_False; 378 sal_uInt16 n = 0; 379 // zur StartPos das erste Redline suchen 380 if( !GetRedline( *pStt, &n ) && n ) 381 --n; 382 bool bDec = false; 383 384 for( ; pNewRedl && n < pRedlineTbl->Count(); bDec ? n : ++n ) 385 { 386 bDec = false; 387 #ifdef DVO_TEST 388 _CHECK_REDLINE( this ) 389 #endif 390 391 SwRedline* pRedl = (*pRedlineTbl)[ n ]; 392 SwPosition* pRStt = pRedl->Start(), 393 * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark() 394 : pRedl->GetPoint(); 395 396 // #i8518# remove empty redlines while we're at it 397 if( ( *pRStt == *pREnd ) && 398 ( pRedl->GetContentIdx() == NULL ) ) 399 { 400 pRedlineTbl->DeleteAndDestroy(n); 401 continue; 402 } 403 404 SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ); 405 406 switch( pNewRedl->GetType() ) 407 { 408 case nsRedlineType_t::REDLINE_INSERT: 409 switch( pRedl->GetType() ) 410 { 411 case nsRedlineType_t::REDLINE_INSERT: 412 if( pRedl->IsOwnRedline( *pNewRedl ) ) 413 { 414 bool bDelete = false; 415 416 // ggfs. verschmelzen? 417 if( (( POS_BEHIND == eCmpPos && 418 IsPrevPos( *pREnd, *pStt ) ) || 419 ( POS_COLLIDE_START == eCmpPos ) || 420 ( POS_OVERLAP_BEHIND == eCmpPos ) ) && 421 pRedl->CanCombine( *pNewRedl ) && 422 ( n+1 >= pRedlineTbl->Count() || 423 ( *(*pRedlineTbl)[ n+1 ]->Start() >= *pEnd && 424 *(*pRedlineTbl)[ n+1 ]->Start() != *pREnd ) ) ) 425 { 426 pRedl->SetEnd( *pEnd, pREnd ); 427 if( !pRedl->HasValidRange() ) 428 { 429 // neu einsortieren 430 pRedlineTbl->Remove( n ); 431 pRedlineTbl->Insert( pRedl ); 432 } 433 434 bError = false; 435 bDelete = true; 436 } 437 else if( (( POS_BEFORE == eCmpPos && 438 IsPrevPos( *pEnd, *pRStt ) ) || 439 ( POS_COLLIDE_END == eCmpPos ) || 440 ( POS_OVERLAP_BEFORE == eCmpPos ) ) && 441 pRedl->CanCombine( *pNewRedl ) && 442 ( !n || 443 *(*pRedlineTbl)[ n-1 ]->End() != *pRStt )) 444 { 445 pRedl->SetStart( *pStt, pRStt ); 446 // neu einsortieren 447 pRedlineTbl->Remove( n ); 448 pRedlineTbl->Insert( pRedl ); 449 450 bError = false; 451 bDelete = true; 452 } 453 else if ( POS_OUTSIDE == eCmpPos ) 454 { 455 // #107164# own insert-over-insert 456 // redlines: just scrap the inside ones 457 pRedlineTbl->Remove( n ); 458 bDec = true; 459 } 460 // <- #107164# 461 else if( POS_OVERLAP_BEHIND == eCmpPos ) 462 { 463 *pStt = *pREnd; 464 if( ( *pStt == *pEnd ) && 465 ( pNewRedl->GetContentIdx() == NULL ) ) 466 bDelete = true; 467 } 468 else if( POS_OVERLAP_BEFORE == eCmpPos ) 469 { 470 *pEnd = *pRStt; 471 if( ( *pStt == *pEnd ) && 472 ( pNewRedl->GetContentIdx() == NULL ) ) 473 bDelete = true; 474 } 475 else if( POS_INSIDE == eCmpPos || POS_EQUAL == eCmpPos) 476 bDelete = true; 477 478 if( bDelete ) 479 { 480 delete pNewRedl, pNewRedl = 0; 481 bCompress = sal_True; 482 } 483 } 484 else if( POS_INSIDE == eCmpPos ) 485 { 486 // aufsplitten 487 if( *pEnd != *pREnd ) 488 { 489 SwRedline* pCpy = new SwRedline( *pRedl ); 490 pCpy->SetStart( *pEnd ); 491 pRedlineTbl->Insert( pCpy ); 492 } 493 pRedl->SetEnd( *pStt, pREnd ); 494 if( ( *pStt == *pRStt ) && 495 ( pRedl->GetContentIdx() == NULL ) ) 496 { 497 pRedlineTbl->DeleteAndDestroy( n ); 498 bDec = true; 499 } 500 else if( !pRedl->HasValidRange() ) 501 { 502 // neu einsortieren 503 pRedlineTbl->Remove( n ); 504 pRedlineTbl->Insert( pRedl ); 505 } 506 } 507 else if ( POS_OUTSIDE == eCmpPos ) 508 { 509 // #102366# handle overlapping redlines in broken 510 // documents 511 512 // split up the new redline, since it covers the 513 // existing redline. Insert the first part, and 514 // progress with the remainder as usual 515 SwRedline* pSplit = new SwRedline( *pNewRedl ); 516 pSplit->SetEnd( *pRStt ); 517 pNewRedl->SetStart( *pREnd ); 518 pRedlineTbl->Insert( pSplit ); 519 if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL ) 520 { 521 delete pNewRedl; 522 pNewRedl = 0; 523 bCompress = true; 524 } 525 } 526 else if ( POS_OVERLAP_BEHIND == eCmpPos ) 527 { 528 // #107164# handle overlapping redlines in broken 529 // documents 530 pNewRedl->SetStart( *pREnd ); 531 } 532 else if ( POS_OVERLAP_BEFORE == eCmpPos ) 533 { 534 // #107164# handle overlapping redlines in broken 535 // documents 536 *pEnd = *pRStt; 537 if( ( *pStt == *pEnd ) && 538 ( pNewRedl->GetContentIdx() == NULL ) ) 539 { 540 delete pNewRedl; 541 pNewRedl = 0; 542 bCompress = true; 543 } 544 } 545 break; 546 case nsRedlineType_t::REDLINE_DELETE: 547 if( POS_INSIDE == eCmpPos ) 548 { 549 // aufsplitten 550 if( *pEnd != *pREnd ) 551 { 552 SwRedline* pCpy = new SwRedline( *pRedl ); 553 pCpy->SetStart( *pEnd ); 554 pRedlineTbl->Insert( pCpy ); 555 } 556 pRedl->SetEnd( *pStt, pREnd ); 557 if( ( *pStt == *pRStt ) && 558 ( pRedl->GetContentIdx() == NULL ) ) 559 { 560 pRedlineTbl->DeleteAndDestroy( n ); 561 bDec = true; 562 } 563 else if( !pRedl->HasValidRange() ) 564 { 565 // neu einsortieren 566 pRedlineTbl->Remove( n ); 567 pRedlineTbl->Insert( pRedl, n ); 568 } 569 } 570 else if ( POS_OUTSIDE == eCmpPos ) 571 { 572 // #102366# handle overlapping redlines in broken 573 // documents 574 575 // split up the new redline, since it covers the 576 // existing redline. Insert the first part, and 577 // progress with the remainder as usual 578 SwRedline* pSplit = new SwRedline( *pNewRedl ); 579 pSplit->SetEnd( *pRStt ); 580 pNewRedl->SetStart( *pREnd ); 581 pRedlineTbl->Insert( pSplit ); 582 if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL ) 583 { 584 delete pNewRedl; 585 pNewRedl = 0; 586 bCompress = true; 587 } 588 } 589 else if ( POS_EQUAL == eCmpPos ) 590 { 591 // #112895# handle identical redlines in broken 592 // documents - delete old (delete) redline 593 pRedlineTbl->DeleteAndDestroy( n ); 594 bDec = true; 595 } 596 else if ( POS_OVERLAP_BEHIND == eCmpPos ) 597 { // Another workaround for broken redlines (#107164#) 598 pNewRedl->SetStart( *pREnd ); 599 } 600 break; 601 case nsRedlineType_t::REDLINE_FORMAT: 602 switch( eCmpPos ) 603 { 604 case POS_OVERLAP_BEFORE: 605 pRedl->SetStart( *pEnd, pRStt ); 606 // neu einsortieren 607 pRedlineTbl->Remove( n ); 608 pRedlineTbl->Insert( pRedl, n ); 609 bDec = true; 610 break; 611 612 case POS_OVERLAP_BEHIND: 613 pRedl->SetEnd( *pStt, pREnd ); 614 if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL ) 615 { 616 pRedlineTbl->DeleteAndDestroy( n ); 617 bDec = true; 618 } 619 break; 620 621 case POS_EQUAL: 622 case POS_OUTSIDE: 623 // ueberlappt den akt. komplett oder hat gleiche 624 // Ausdehung, dann muss der alte geloescht werden 625 pRedlineTbl->DeleteAndDestroy( n ); 626 bDec = true; 627 break; 628 629 case POS_INSIDE: 630 // ueberlappt den akt. komplett, dann muss 631 // der neue gesplittet oder verkuertzt werden 632 if( *pEnd != *pREnd ) 633 { 634 if( *pEnd != *pRStt ) 635 { 636 SwRedline* pNew = new SwRedline( *pRedl ); 637 pNew->SetStart( *pEnd ); 638 pRedl->SetEnd( *pStt, pREnd ); 639 if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL ) 640 pRedlineTbl->DeleteAndDestroy( n ); 641 AppendRedline( pNew, bCallDelete ); 642 n = 0; // neu Aufsetzen 643 bDec = true; 644 } 645 } 646 else 647 pRedl->SetEnd( *pStt, pREnd ); 648 break; 649 default: 650 break; 651 } 652 break; 653 default: 654 break; 655 } 656 break; 657 658 case nsRedlineType_t::REDLINE_DELETE: 659 switch( pRedl->GetType() ) 660 { 661 case nsRedlineType_t::REDLINE_DELETE: 662 switch( eCmpPos ) 663 { 664 case POS_OUTSIDE: 665 { 666 // ueberlappt den akt. komplett 667 // dann muss der neue gesplittet werden 668 if( *pEnd != *pREnd ) 669 { 670 SwRedline* pNew = new SwRedline( *pNewRedl ); 671 pNew->SetStart( *pREnd ); 672 pNewRedl->SetEnd( *pRStt, pEnd ); 673 AppendRedline( pNew, bCallDelete ); 674 n = 0; // neu Aufsetzen 675 bDec = true; 676 } 677 else 678 pNewRedl->SetEnd( *pRStt, pEnd ); 679 } 680 break; 681 682 case POS_INSIDE: 683 case POS_EQUAL: 684 delete pNewRedl, pNewRedl = 0; 685 bCompress = sal_True; 686 break; 687 688 case POS_OVERLAP_BEFORE: 689 case POS_OVERLAP_BEHIND: 690 if( pRedl->IsOwnRedline( *pNewRedl ) && 691 // 1 == pRedl->GetStackCount() && 692 pRedl->CanCombine( *pNewRedl )) 693 { 694 // dann kann das zusammengefasst werden, sprich 695 // der neue deckt das schon ab. 696 if( POS_OVERLAP_BEHIND == eCmpPos ) 697 pNewRedl->SetStart( *pRStt, pStt ); 698 else 699 pNewRedl->SetEnd( *pREnd, pEnd ); 700 pRedlineTbl->DeleteAndDestroy( n ); 701 bDec = true; 702 } 703 else if( POS_OVERLAP_BEHIND == eCmpPos ) 704 pNewRedl->SetStart( *pREnd, pStt ); 705 else 706 pNewRedl->SetEnd( *pRStt, pEnd ); 707 break; 708 709 case POS_COLLIDE_START: 710 case POS_COLLIDE_END: 711 if( pRedl->IsOwnRedline( *pNewRedl ) && 712 // 1 == pRedl->GetStackCount() && 713 pRedl->CanCombine( *pNewRedl ) ) 714 { 715 if( IsHideChanges( eRedlineMode )) 716 { 717 // dann erstmal sichtbar machen, bevor 718 // die zusammengefasst werden koennen! 719 // Damit pNew auch beim Verschieben der 720 // Indizies behandelt wird, erstmal 721 // temporaer einfuegen 722 pRedlineTbl->SavePtrInArr( pNewRedl ); 723 pRedl->Show(); 724 pRedlineTbl->Remove( pRedlineTbl->GetPos(pNewRedl )); 725 pRStt = pRedl->Start(); 726 pREnd = pRedl->End(); 727 } 728 729 // dann kann das zusammengefasst werden, sprich 730 // der neue deckt das schon ab. 731 if( POS_COLLIDE_START == eCmpPos ) 732 pNewRedl->SetStart( *pRStt, pStt ); 733 else 734 pNewRedl->SetEnd( *pREnd, pEnd ); 735 736 // delete current (below), and restart process with 737 // previous 738 sal_uInt16 nToBeDeleted = n; 739 bDec = true; 740 741 // #107359# Do it again, Sam! 742 // If you can do it for them, you can do it for me. 743 if( *(pNewRedl->Start()) <= *pREnd ) 744 { 745 // Whoooah, we just extended the new 'redline' 746 // beyond previous redlines, so better start 747 // again. Of course this is not supposed to 748 // happen, and in an ideal world it doesn't, 749 // but unfortunately this code is buggy and 750 // totally rotten so it does happen and we 751 // better fix it. 752 n = 0; 753 bDec = true; 754 } 755 756 pRedlineTbl->DeleteAndDestroy( nToBeDeleted ); 757 } 758 break; 759 default: 760 break; 761 } 762 break; 763 764 case nsRedlineType_t::REDLINE_INSERT: 765 { 766 // b62341295: Do not throw away redlines 767 // even if they are not allowed to be combined 768 RedlineMode_t eOld = eRedlineMode; 769 if( !( eOld & nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) && 770 pRedl->IsOwnRedline( *pNewRedl ) ) 771 { 772 773 // auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig 774 // zusammen fasst! Der ShowMode muss erhalten bleiben! 775 eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)); 776 switch( eCmpPos ) 777 { 778 case POS_EQUAL: 779 bCompress = sal_True; 780 pRedlineTbl->DeleteAndDestroy( n ); 781 bDec = true; 782 // kein break! 783 784 case POS_INSIDE: 785 if( bCallDelete ) 786 { 787 eRedlineMode = (RedlineMode_t)(eRedlineMode | nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES); 788 789 // #98863# DeleteAndJoin does not yield the 790 // desired result if there is no paragraph to 791 // join with, i.e. at the end of the document. 792 // For this case, we completely delete the 793 // paragraphs (if, of course, we also start on 794 // a paragraph boundary). 795 if( (pStt->nContent == 0) && 796 pEnd->nNode.GetNode().IsEndNode() ) 797 { 798 pEnd->nNode--; 799 pEnd->nContent.Assign( 800 pEnd->nNode.GetNode().GetTxtNode(), 0); 801 DelFullPara( *pNewRedl ); 802 } 803 else 804 DeleteAndJoin( *pNewRedl ); 805 806 bCompress = sal_True; 807 } 808 delete pNewRedl, pNewRedl = 0; 809 break; 810 811 case POS_OUTSIDE: 812 { 813 pRedlineTbl->Remove( n ); 814 bDec = true; 815 // damit pNew auch beim Verschieben der Indizies 816 // behandelt wird, erstmal temp. einfuegen 817 if( bCallDelete ) 818 { 819 pRedlineTbl->SavePtrInArr( pNewRedl ); 820 DeleteAndJoin( *pRedl ); 821 sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl ); 822 if( USHRT_MAX != nFnd ) 823 pRedlineTbl->Remove( nFnd ); 824 else 825 pNewRedl = 0; 826 } 827 delete pRedl; 828 } 829 break; 830 831 case POS_OVERLAP_BEFORE: 832 { 833 SwPaM aPam( *pRStt, *pEnd ); 834 835 if( *pEnd == *pREnd ) 836 pRedlineTbl->DeleteAndDestroy( n ); 837 else 838 { 839 pRedl->SetStart( *pEnd, pRStt ); 840 // neu einsortieren 841 pRedlineTbl->Remove( n ); 842 pRedlineTbl->Insert( pRedl, n ); 843 } 844 845 if( bCallDelete ) 846 { 847 // damit pNew auch beim Verschieben der Indizies 848 // behandelt wird, erstmal temp. einfuegen 849 pRedlineTbl->SavePtrInArr( pNewRedl ); 850 DeleteAndJoin( aPam ); 851 sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl ); 852 if( USHRT_MAX != nFnd ) 853 pRedlineTbl->Remove( nFnd ); 854 else 855 pNewRedl = 0; 856 n = 0; // neu Aufsetzen 857 } 858 bDec = true; 859 } 860 break; 861 862 case POS_OVERLAP_BEHIND: 863 { 864 SwPaM aPam( *pStt, *pREnd ); 865 866 if( *pStt == *pRStt ) 867 { 868 pRedlineTbl->DeleteAndDestroy( n ); 869 bDec = true; 870 } 871 else 872 pRedl->SetEnd( *pStt, pREnd ); 873 874 if( bCallDelete ) 875 { 876 // damit pNew auch beim Verschieben der Indizies 877 // behandelt wird, erstmal temp. einfuegen 878 pRedlineTbl->SavePtrInArr( pNewRedl ); 879 DeleteAndJoin( aPam ); 880 sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl ); 881 if( USHRT_MAX != nFnd ) 882 pRedlineTbl->Remove( nFnd ); 883 else 884 pNewRedl = 0; 885 n = 0; // neu Aufsetzen 886 bDec = true; 887 } 888 } 889 break; 890 default: 891 break; 892 } 893 894 eRedlineMode = eOld; 895 } 896 else 897 { 898 // it may be necessary to split the existing redline in 899 // two. In this case, pRedl will be changed to cover 900 // only part of it's former range, and pNew will cover 901 // the remainder. 902 SwRedline* pNew = 0; 903 904 switch( eCmpPos ) 905 { 906 case POS_EQUAL: 907 { 908 pRedl->PushData( *pNewRedl ); 909 delete pNewRedl, pNewRedl = 0; 910 if( IsHideChanges( eRedlineMode )) 911 pRedl->Hide(); 912 bCompress = sal_True; 913 } 914 break; 915 916 case POS_INSIDE: 917 { 918 if( *pRStt == *pStt ) 919 { 920 // --> mst 2010-05-17 #i97421# 921 // redline w/out extent loops 922 if (*pStt != *pEnd) 923 // <-- 924 { 925 pNewRedl->PushData( *pRedl, sal_False ); 926 pRedl->SetStart( *pEnd, pRStt ); 927 // re-insert 928 pRedlineTbl->Remove( n ); 929 pRedlineTbl->Insert( pRedl, n ); 930 bDec = true; 931 } 932 } 933 else 934 { 935 pNewRedl->PushData( *pRedl, sal_False ); 936 if( *pREnd != *pEnd ) 937 { 938 pNew = new SwRedline( *pRedl ); 939 pNew->SetStart( *pEnd ); 940 } 941 pRedl->SetEnd( *pStt, pREnd ); 942 if( !pRedl->HasValidRange() ) 943 { 944 // neu einsortieren 945 pRedlineTbl->Remove( n ); 946 pRedlineTbl->Insert( pRedl, n ); 947 } 948 } 949 } 950 break; 951 952 case POS_OUTSIDE: 953 { 954 pRedl->PushData( *pNewRedl ); 955 if( *pEnd == *pREnd ) 956 pNewRedl->SetEnd( *pRStt, pEnd ); 957 else 958 { 959 pNew = new SwRedline( *pNewRedl ); 960 pNew->SetEnd( *pRStt ); 961 pNewRedl->SetStart( *pREnd, pStt ); 962 } 963 bCompress = sal_True; 964 } 965 break; 966 967 case POS_OVERLAP_BEFORE: 968 { 969 if( *pEnd == *pREnd ) 970 { 971 pRedl->PushData( *pNewRedl ); 972 pNewRedl->SetEnd( *pRStt, pEnd ); 973 if( IsHideChanges( eRedlineMode )) 974 { 975 pRedlineTbl->SavePtrInArr( pNewRedl ); 976 pRedl->Hide(); 977 pRedlineTbl->Remove( 978 pRedlineTbl->GetPos(pNewRedl )); 979 } 980 } 981 else 982 { 983 pNew = new SwRedline( *pRedl ); 984 pNew->PushData( *pNewRedl ); 985 pNew->SetEnd( *pEnd ); 986 pNewRedl->SetEnd( *pRStt, pEnd ); 987 pRedl->SetStart( *pNew->End(), pRStt ) ; 988 // neu einsortieren 989 pRedlineTbl->Remove( n ); 990 pRedlineTbl->Insert( pRedl ); 991 bDec = true; 992 } 993 } 994 break; 995 996 case POS_OVERLAP_BEHIND: 997 { 998 if( *pStt == *pRStt ) 999 { 1000 pRedl->PushData( *pNewRedl ); 1001 pNewRedl->SetStart( *pREnd, pStt ); 1002 if( IsHideChanges( eRedlineMode )) 1003 { 1004 pRedlineTbl->SavePtrInArr( pNewRedl ); 1005 pRedl->Hide(); 1006 pRedlineTbl->Remove( 1007 pRedlineTbl->GetPos(pNewRedl )); 1008 } 1009 } 1010 else 1011 { 1012 pNew = new SwRedline( *pRedl ); 1013 pNew->PushData( *pNewRedl ); 1014 pNew->SetStart( *pStt ); 1015 pNewRedl->SetStart( *pREnd, pStt ); 1016 pRedl->SetEnd( *pNew->Start(), pREnd ); 1017 if( !pRedl->HasValidRange() ) 1018 { 1019 // neu einsortieren 1020 pRedlineTbl->Remove( n ); 1021 pRedlineTbl->Insert( pRedl ); 1022 } 1023 } 1024 } 1025 break; 1026 default: 1027 break; 1028 } 1029 1030 // insert the pNew part (if it exists) 1031 if( pNew ) 1032 { 1033 // AppendRedline( pNew, bCallDelete ); 1034 //sal_Bool bRet = 1035 pRedlineTbl->Insert( pNew ); 1036 1037 // pNew must be deleted if Insert() wasn't 1038 // successful. But that can't happen, since pNew is 1039 // part of the original pRedl redline. 1040 // ASSERT( bRet, "Can't insert existing redline?" ); 1041 1042 // restart (now with pRedl being split up) 1043 n = 0; 1044 bDec = true; 1045 } 1046 } 1047 } 1048 break; 1049 1050 case nsRedlineType_t::REDLINE_FORMAT: 1051 switch( eCmpPos ) 1052 { 1053 case POS_OVERLAP_BEFORE: 1054 pRedl->SetStart( *pEnd, pRStt ); 1055 // neu einsortieren 1056 pRedlineTbl->Remove( n ); 1057 pRedlineTbl->Insert( pRedl, n ); 1058 bDec = true; 1059 break; 1060 1061 case POS_OVERLAP_BEHIND: 1062 pRedl->SetEnd( *pStt, pREnd ); 1063 break; 1064 1065 case POS_EQUAL: 1066 case POS_OUTSIDE: 1067 // ueberlappt den akt. komplett oder hat gleiche 1068 // Ausdehung, dann muss der alte geloescht werden 1069 pRedlineTbl->DeleteAndDestroy( n ); 1070 bDec = true; 1071 break; 1072 1073 case POS_INSIDE: 1074 // ueberlappt den akt. komplett, dann muss 1075 // der neue gesplittet oder verkuertzt werden 1076 if( *pEnd != *pREnd ) 1077 { 1078 if( *pEnd != *pRStt ) 1079 { 1080 SwRedline* pNew = new SwRedline( *pRedl ); 1081 pNew->SetStart( *pEnd ); 1082 pRedl->SetEnd( *pStt, pREnd ); 1083 if( ( *pStt == *pRStt ) && 1084 ( pRedl->GetContentIdx() == NULL ) ) 1085 pRedlineTbl->DeleteAndDestroy( n ); 1086 AppendRedline( pNew, bCallDelete ); 1087 n = 0; // neu Aufsetzen 1088 bDec = true; 1089 } 1090 } 1091 else 1092 pRedl->SetEnd( *pStt, pREnd ); 1093 break; 1094 default: 1095 break; 1096 } 1097 break; 1098 default: 1099 break; 1100 } 1101 break; 1102 1103 case nsRedlineType_t::REDLINE_FORMAT: 1104 switch( pRedl->GetType() ) 1105 { 1106 case nsRedlineType_t::REDLINE_INSERT: 1107 case nsRedlineType_t::REDLINE_DELETE: 1108 switch( eCmpPos ) 1109 { 1110 case POS_OVERLAP_BEFORE: 1111 pNewRedl->SetEnd( *pRStt, pEnd ); 1112 break; 1113 1114 case POS_OVERLAP_BEHIND: 1115 pNewRedl->SetStart( *pREnd, pStt ); 1116 break; 1117 1118 case POS_EQUAL: 1119 case POS_INSIDE: 1120 delete pNewRedl, pNewRedl = 0; 1121 break; 1122 1123 case POS_OUTSIDE: 1124 // ueberlappt den akt. komplett, dann muss 1125 // der neue gesplittet oder verkuerzt werden 1126 if( *pEnd != *pREnd ) 1127 { 1128 if( *pEnd != *pRStt ) 1129 { 1130 SwRedline* pNew = new SwRedline( *pNewRedl ); 1131 pNew->SetStart( *pREnd ); 1132 pNewRedl->SetEnd( *pRStt, pEnd ); 1133 AppendRedline( pNew, bCallDelete ); 1134 n = 0; // neu Aufsetzen 1135 bDec = true; 1136 } 1137 } 1138 else 1139 pNewRedl->SetEnd( *pRStt, pEnd ); 1140 break; 1141 default: 1142 break; 1143 } 1144 break; 1145 case nsRedlineType_t::REDLINE_FORMAT: 1146 switch( eCmpPos ) 1147 { 1148 case POS_OUTSIDE: 1149 case POS_EQUAL: 1150 { 1151 // ueberlappt den akt. komplett oder hat gleiche 1152 // Ausdehnung, dann muss der alte geloescht werden 1153 pRedlineTbl->DeleteAndDestroy( n ); 1154 bDec = true; 1155 } 1156 break; 1157 1158 case POS_INSIDE: 1159 if( pRedl->IsOwnRedline( *pNewRedl ) && 1160 pRedl->CanCombine( *pNewRedl )) 1161 // ein eigenes kann komplett ignoriert werden 1162 delete pNewRedl, pNewRedl = 0; 1163 1164 else if( *pREnd == *pEnd ) 1165 // ansonsten nur den akt. verkuerzen 1166 pRedl->SetEnd( *pStt, pREnd ); 1167 else if( *pRStt == *pStt ) 1168 { 1169 // ansonsten nur den akt. verkuerzen 1170 pRedl->SetStart( *pEnd, pRStt ); 1171 // neu einsortieren 1172 pRedlineTbl->Remove( n ); 1173 pRedlineTbl->Insert( pRedl, n ); 1174 bDec = true; 1175 } 1176 else 1177 { 1178 // liegt komplett im akt. 1179 // dann muss der gesplittet werden 1180 SwRedline* pNew = new SwRedline( *pRedl ); 1181 pNew->SetStart( *pEnd ); 1182 pRedl->SetEnd( *pStt, pREnd ); 1183 AppendRedline( pNew, bCallDelete ); 1184 n = 0; // neu Aufsetzen 1185 bDec = true; 1186 } 1187 break; 1188 1189 case POS_OVERLAP_BEFORE: 1190 case POS_OVERLAP_BEHIND: 1191 if( pRedl->IsOwnRedline( *pNewRedl ) && 1192 pRedl->CanCombine( *pNewRedl )) 1193 { 1194 // dann kann das zusammengefasst werden, sprich 1195 // der neue deckt das schon ab. 1196 if( POS_OVERLAP_BEHIND == eCmpPos ) 1197 pNewRedl->SetStart( *pRStt, pStt ); 1198 else 1199 pNewRedl->SetEnd( *pREnd, pEnd ); 1200 pRedlineTbl->DeleteAndDestroy( n ); 1201 bDec = 0; 1202 } 1203 else if( POS_OVERLAP_BEHIND == eCmpPos ) 1204 pNewRedl->SetStart( *pREnd, pStt ); 1205 else 1206 pNewRedl->SetEnd( *pRStt, pEnd ); 1207 break; 1208 1209 case POS_COLLIDE_END: 1210 if( pRedl->IsOwnRedline( *pNewRedl ) && 1211 pRedl->CanCombine( *pNewRedl ) && n && 1212 *(*pRedlineTbl)[ n-1 ]->End() < *pStt ) 1213 { 1214 // dann kann das zusammengefasst werden, sprich 1215 // der neue deckt das schon ab. 1216 pNewRedl->SetEnd( *pREnd, pEnd ); 1217 pRedlineTbl->DeleteAndDestroy( n ); 1218 bDec = true; 1219 } 1220 break; 1221 case POS_COLLIDE_START: 1222 if( pRedl->IsOwnRedline( *pNewRedl ) && 1223 pRedl->CanCombine( *pNewRedl ) && 1224 n+1 < pRedlineTbl->Count() && 1225 *(*pRedlineTbl)[ n+1 ]->Start() < *pEnd ) 1226 { 1227 // dann kann das zusammengefasst werden, sprich 1228 // der neue deckt das schon ab. 1229 pNewRedl->SetStart( *pRStt, pStt ); 1230 pRedlineTbl->DeleteAndDestroy( n ); 1231 bDec = true; 1232 } 1233 break; 1234 default: 1235 break; 1236 } 1237 break; 1238 default: 1239 break; 1240 } 1241 break; 1242 1243 1244 case nsRedlineType_t::REDLINE_FMTCOLL: 1245 // wie soll das verhalten sein???? 1246 // erstmal so einfuegen 1247 break; 1248 default: 1249 break; 1250 } 1251 } 1252 1253 if( pNewRedl ) 1254 { 1255 if( ( *pStt == *pEnd ) && 1256 ( pNewRedl->GetContentIdx() == NULL ) ) 1257 { // Do not insert empty redlines 1258 delete pNewRedl; 1259 pNewRedl = 0; 1260 } 1261 else 1262 pRedlineTbl->Insert( pNewRedl ); 1263 } 1264 1265 if( bCompress ) 1266 CompressRedlines(); 1267 } 1268 else 1269 { 1270 if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() ) 1271 { 1272 RedlineMode_t eOld = eRedlineMode; 1273 // auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig 1274 // zusammen fasst! Der ShowMode muss erhalten bleiben! 1275 eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)); 1276 DeleteAndJoin( *pNewRedl ); 1277 eRedlineMode = eOld; 1278 } 1279 delete pNewRedl, pNewRedl = 0; 1280 } 1281 _CHECK_REDLINE( this ) 1282 1283 return ( 0 != pNewRedl ) || !bError; 1284 } 1285 1286 void SwDoc::CompressRedlines() 1287 { 1288 _CHECK_REDLINE( this ) 1289 1290 void (SwRedline::*pFnc)(sal_uInt16) = 0; 1291 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode ) 1292 { 1293 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE: 1294 pFnc = &SwRedline::Show; 1295 break; 1296 case nsRedlineMode_t::REDLINE_SHOW_INSERT: 1297 pFnc = &SwRedline::Hide; 1298 break; 1299 } 1300 1301 // versuche gleiche zusammenzufassen 1302 for( sal_uInt16 n = 1; n < pRedlineTbl->Count(); ++n ) 1303 { 1304 SwRedline* pPrev = (*pRedlineTbl)[ n-1 ], 1305 * pCur = (*pRedlineTbl)[ n ]; 1306 const SwPosition* pPrevStt = pPrev->Start(), 1307 * pPrevEnd = pPrevStt == pPrev->GetPoint() 1308 ? pPrev->GetMark() : pPrev->GetPoint(); 1309 const SwPosition* pCurStt = pCur->Start(), 1310 * pCurEnd = pCurStt == pCur->GetPoint() 1311 ? pCur->GetMark() : pCur->GetPoint(); 1312 if( *pPrevEnd == *pCurStt && pPrev->CanCombine( *pCur ) && 1313 pPrevStt->nNode.GetNode().StartOfSectionNode() == 1314 pCurEnd->nNode.GetNode().StartOfSectionNode() && 1315 !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() ) 1316 { 1317 // dann koennen die zusammen gefasst werden 1318 pPrev->Show(); 1319 pCur->Show(); 1320 1321 pPrev->SetEnd( *pCur->End() ); 1322 pRedlineTbl->DeleteAndDestroy( n ); 1323 --n; 1324 if( pFnc ) 1325 (pPrev->*pFnc)(0); 1326 } 1327 } 1328 _CHECK_REDLINE( this ) 1329 } 1330 1331 bool SwDoc::SplitRedline( const SwPaM& rRange ) 1332 { 1333 sal_Bool bChg = sal_False; 1334 sal_uInt16 n = 0; 1335 const SwPosition* pStt = rRange.Start(), 1336 * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark() 1337 : rRange.GetPoint(); 1338 GetRedline( *pStt, &n ); 1339 for( ; n < pRedlineTbl->Count() ; ++n ) 1340 { 1341 SwRedline* pTmp = (*pRedlineTbl)[ n ]; 1342 SwPosition* pTStt = pTmp->Start(), 1343 * pTEnd = pTStt == pTmp->GetPoint() ? pTmp->GetMark() 1344 : pTmp->GetPoint(); 1345 if( *pTStt <= *pStt && *pStt <= *pTEnd && 1346 *pTStt <= *pEnd && *pEnd <= *pTEnd ) 1347 { 1348 bChg = sal_True; 1349 int nn = 0; 1350 if( *pStt == *pTStt ) 1351 nn += 1; 1352 if( *pEnd == *pTEnd ) 1353 nn += 2; 1354 1355 SwRedline* pNew = 0; 1356 switch( nn ) 1357 { 1358 case 0: 1359 pNew = new SwRedline( *pTmp ); 1360 pTmp->SetEnd( *pStt, pTEnd ); 1361 pNew->SetStart( *pEnd ); 1362 break; 1363 1364 case 1: 1365 *pTStt = *pEnd; 1366 break; 1367 1368 case 2: 1369 *pTEnd = *pStt; 1370 break; 1371 1372 case 3: 1373 pTmp->InvalidateRange(); 1374 pRedlineTbl->DeleteAndDestroy( n-- ); 1375 pTmp = 0; 1376 break; 1377 } 1378 if( pTmp && !pTmp->HasValidRange() ) 1379 { 1380 // neu einsortieren 1381 pRedlineTbl->Remove( n ); 1382 pRedlineTbl->Insert( pTmp, n ); 1383 } 1384 if( pNew ) 1385 pRedlineTbl->Insert( pNew, n ); 1386 } 1387 else if( *pEnd < *pTStt ) 1388 break; 1389 } 1390 return bChg; 1391 } 1392 1393 bool SwDoc::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo, 1394 sal_uInt16 nDelType ) 1395 { 1396 if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & eRedlineMode || 1397 !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() ) 1398 return sal_False; 1399 1400 sal_Bool bChg = sal_False; 1401 1402 if (bSaveInUndo && GetIDocumentUndoRedo().DoesUndo()) 1403 { 1404 SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange ); 1405 if( pUndo->GetRedlSaveCount() ) 1406 { 1407 GetIDocumentUndoRedo().AppendUndo(pUndo); 1408 } 1409 else 1410 delete pUndo; 1411 } 1412 1413 const SwPosition* pStt = rRange.Start(), 1414 * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark() 1415 : rRange.GetPoint(); 1416 sal_uInt16 n = 0; 1417 GetRedline( *pStt, &n ); 1418 for( ; n < pRedlineTbl->Count() ; ++n ) 1419 { 1420 SwRedline* pRedl = (*pRedlineTbl)[ n ]; 1421 if( USHRT_MAX != nDelType && nDelType != pRedl->GetType() ) 1422 continue; 1423 1424 SwPosition* pRStt = pRedl->Start(), 1425 * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark() 1426 : pRedl->GetPoint(); 1427 sal_Bool bDel = sal_False; 1428 switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) ) 1429 { 1430 case POS_EQUAL: 1431 case POS_OUTSIDE: 1432 bDel = sal_True; 1433 break; 1434 1435 case POS_OVERLAP_BEFORE: 1436 if( *pEnd == *pREnd ) 1437 bDel = sal_True; 1438 else 1439 { 1440 pRedl->InvalidateRange(); 1441 pRedl->SetStart( *pEnd, pRStt ); 1442 // neu einsortieren 1443 pRedlineTbl->Remove( n ); 1444 pRedlineTbl->Insert( pRedl ); 1445 --n; 1446 } 1447 break; 1448 1449 case POS_OVERLAP_BEHIND: 1450 if( *pStt == *pRStt ) 1451 bDel = sal_True; 1452 else 1453 { 1454 pRedl->InvalidateRange(); 1455 pRedl->SetEnd( *pStt, pREnd ); 1456 if( !pRedl->HasValidRange() ) 1457 { 1458 // neu einsortieren 1459 pRedlineTbl->Remove( n ); 1460 pRedlineTbl->Insert( pRedl ); 1461 --n; 1462 } 1463 } 1464 break; 1465 1466 case POS_INSIDE: 1467 { 1468 // der muss gesplittet werden 1469 pRedl->InvalidateRange(); 1470 if( *pRStt == *pStt ) 1471 { 1472 pRedl->SetStart( *pEnd, pRStt ); 1473 // neu einsortieren 1474 pRedlineTbl->Remove( n ); 1475 pRedlineTbl->Insert( pRedl ); 1476 --n; 1477 } 1478 else 1479 { 1480 SwRedline* pCpy; 1481 if( *pREnd != *pEnd ) 1482 { 1483 pCpy = new SwRedline( *pRedl ); 1484 pCpy->SetStart( *pEnd ); 1485 } 1486 else 1487 pCpy = 0; 1488 pRedl->SetEnd( *pStt, pREnd ); 1489 if( !pRedl->HasValidRange() ) 1490 { 1491 // neu einsortieren 1492 pRedlineTbl->Remove( pRedlineTbl->GetPos( pRedl )); 1493 pRedlineTbl->Insert( pRedl ); 1494 --n; 1495 } 1496 if( pCpy ) 1497 pRedlineTbl->Insert( pCpy ); 1498 } 1499 } 1500 break; 1501 1502 case POS_COLLIDE_END: 1503 case POS_BEFORE: 1504 n = pRedlineTbl->Count(); 1505 break; 1506 default: 1507 break; 1508 } 1509 1510 if( bDel ) 1511 { 1512 pRedl->InvalidateRange(); 1513 pRedlineTbl->DeleteAndDestroy( n-- ); 1514 bChg = sal_True; 1515 } 1516 } 1517 1518 if( bChg ) 1519 SetModified(); 1520 1521 return bChg; 1522 } 1523 1524 bool SwDoc::DeleteRedline( const SwStartNode& rNode, bool bSaveInUndo, 1525 sal_uInt16 nDelType ) 1526 { 1527 SwPaM aTemp(*rNode.EndOfSectionNode(), rNode); 1528 return DeleteRedline(aTemp, bSaveInUndo, nDelType); 1529 } 1530 1531 sal_uInt16 SwDoc::GetRedlinePos( const SwNode& rNd, sal_uInt16 nType ) const 1532 { 1533 const sal_uLong nNdIdx = rNd.GetIndex(); 1534 for( sal_uInt16 n = 0; n < pRedlineTbl->Count() ; ++n ) 1535 { 1536 const SwRedline* pTmp = (*pRedlineTbl)[ n ]; 1537 sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(), 1538 nMk = pTmp->GetMark()->nNode.GetIndex(); 1539 if( nPt < nMk ) { long nTmp = nMk; nMk = nPt; nPt = nTmp; } 1540 1541 if( ( USHRT_MAX == nType || nType == pTmp->GetType()) && 1542 nMk <= nNdIdx && nNdIdx <= nPt ) 1543 return n; 1544 1545 if( nMk > nNdIdx ) 1546 break; 1547 } 1548 return USHRT_MAX; 1549 } 1550 1551 const SwRedline* SwDoc::GetRedline( const SwPosition& rPos, 1552 sal_uInt16* pFndPos ) const 1553 { 1554 sal_uInt16 nO = pRedlineTbl->Count(), nM, nU = 0; 1555 if( nO > 0 ) 1556 { 1557 nO--; 1558 while( nU <= nO ) 1559 { 1560 nM = nU + ( nO - nU ) / 2; 1561 const SwRedline* pRedl = (*pRedlineTbl)[ nM ]; 1562 const SwPosition* pStt = pRedl->Start(); 1563 const SwPosition* pEnd = pStt == pRedl->GetPoint() 1564 ? pRedl->GetMark() 1565 : pRedl->GetPoint(); 1566 if( pEnd == pStt 1567 ? *pStt == rPos 1568 : ( *pStt <= rPos && rPos < *pEnd ) ) 1569 { 1570 /* #107318# returned wrong redline ???*/ 1571 while( nM && rPos == *(*pRedlineTbl)[ nM - 1 ]->End() && 1572 rPos == *(*pRedlineTbl)[ nM - 1 ]->Start() ) 1573 { 1574 --nM; 1575 pRedl = (*pRedlineTbl)[ nM ]; 1576 } 1577 1578 if( pFndPos ) 1579 *pFndPos = nM; 1580 return pRedl; 1581 } 1582 else if( *pEnd <= rPos ) 1583 nU = nM + 1; 1584 else if( nM == 0 ) 1585 { 1586 if( pFndPos ) 1587 *pFndPos = nU; 1588 return 0; 1589 } 1590 else 1591 nO = nM - 1; 1592 } 1593 } 1594 if( pFndPos ) 1595 *pFndPos = nU; 1596 return 0; 1597 } 1598 1599 typedef sal_Bool (*Fn_AcceptReject)( SwRedlineTbl& rArr, sal_uInt16& rPos, 1600 sal_Bool bCallDelete, 1601 const SwPosition* pSttRng, 1602 const SwPosition* pEndRng); 1603 1604 sal_Bool lcl_AcceptRedline( SwRedlineTbl& rArr, sal_uInt16& rPos, 1605 sal_Bool bCallDelete, 1606 const SwPosition* pSttRng = 0, 1607 const SwPosition* pEndRng = 0 ) 1608 { 1609 sal_Bool bRet = sal_True; 1610 SwRedline* pRedl = rArr[ rPos ]; 1611 SwPosition *pRStt = 0, *pREnd = 0; 1612 SwComparePosition eCmp = POS_OUTSIDE; 1613 if( pSttRng && pEndRng ) 1614 { 1615 pRStt = pRedl->Start(); 1616 pREnd = pRedl->End(); 1617 eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd ); 1618 } 1619 1620 pRedl->InvalidateRange(); 1621 1622 switch( pRedl->GetType() ) 1623 { 1624 case nsRedlineType_t::REDLINE_INSERT: 1625 case nsRedlineType_t::REDLINE_FORMAT: 1626 { 1627 sal_Bool bCheck = sal_False, bReplace = sal_False; 1628 switch( eCmp ) 1629 { 1630 case POS_INSIDE: 1631 if( *pSttRng == *pRStt ) 1632 pRedl->SetStart( *pEndRng, pRStt ); 1633 else 1634 { 1635 if( *pEndRng != *pREnd ) 1636 { 1637 // aufsplitten 1638 SwRedline* pNew = new SwRedline( *pRedl ); 1639 pNew->SetStart( *pEndRng ); 1640 rArr.Insert( pNew ); ++rPos; 1641 } 1642 pRedl->SetEnd( *pSttRng, pREnd ); 1643 bCheck = sal_True; 1644 } 1645 break; 1646 1647 case POS_OVERLAP_BEFORE: 1648 pRedl->SetStart( *pEndRng, pRStt ); 1649 bReplace = sal_True; 1650 break; 1651 1652 case POS_OVERLAP_BEHIND: 1653 pRedl->SetEnd( *pSttRng, pREnd ); 1654 bCheck = sal_True; 1655 break; 1656 1657 case POS_OUTSIDE: 1658 case POS_EQUAL: 1659 rArr.DeleteAndDestroy( rPos-- ); 1660 break; 1661 1662 default: 1663 bRet = sal_False; 1664 } 1665 1666 if( bReplace || ( bCheck && !pRedl->HasValidRange() )) 1667 { 1668 // neu einsortieren 1669 rArr.Remove( rArr.GetPos( pRedl )); 1670 rArr.Insert( pRedl ); 1671 } 1672 } 1673 break; 1674 case nsRedlineType_t::REDLINE_DELETE: 1675 { 1676 SwDoc& rDoc = *pRedl->GetDoc(); 1677 const SwPosition *pDelStt = 0, *pDelEnd = 0; 1678 sal_Bool bDelRedl = sal_False; 1679 switch( eCmp ) 1680 { 1681 case POS_INSIDE: 1682 if( bCallDelete ) 1683 { 1684 pDelStt = pSttRng; 1685 pDelEnd = pEndRng; 1686 } 1687 break; 1688 1689 case POS_OVERLAP_BEFORE: 1690 if( bCallDelete ) 1691 { 1692 pDelStt = pRStt; 1693 pDelEnd = pEndRng; 1694 } 1695 break; 1696 case POS_OVERLAP_BEHIND: 1697 if( bCallDelete ) 1698 { 1699 pDelStt = pREnd; 1700 pDelEnd = pSttRng; 1701 } 1702 break; 1703 1704 case POS_OUTSIDE: 1705 case POS_EQUAL: 1706 { 1707 rArr.Remove( rPos-- ); 1708 bDelRedl = sal_True; 1709 if( bCallDelete ) 1710 { 1711 pDelStt = pRedl->Start(); 1712 pDelEnd = pRedl->End(); 1713 } 1714 } 1715 break; 1716 default: 1717 bRet = sal_False; 1718 } 1719 1720 if( pDelStt && pDelEnd ) 1721 { 1722 SwPaM aPam( *pDelStt, *pDelEnd ); 1723 SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode(); 1724 SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode(); 1725 1726 if( bDelRedl ) 1727 delete pRedl; 1728 1729 RedlineMode_t eOld = rDoc.GetRedlineMode(); 1730 rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE))); 1731 1732 if( pCSttNd && pCEndNd ) 1733 rDoc.DeleteAndJoin( aPam ); 1734 else 1735 { 1736 rDoc.DeleteRange( aPam ); 1737 1738 if( pCSttNd && !pCEndNd ) 1739 { 1740 aPam.GetBound( sal_True ).nContent.Assign( 0, 0 ); 1741 aPam.GetBound( sal_False ).nContent.Assign( 0, 0 ); 1742 aPam.DeleteMark(); 1743 rDoc.DelFullPara( aPam ); 1744 } 1745 } 1746 rDoc.SetRedlineMode_intern( eOld ); 1747 } 1748 else if( bDelRedl ) 1749 delete pRedl; 1750 } 1751 break; 1752 1753 case nsRedlineType_t::REDLINE_FMTCOLL: 1754 rArr.DeleteAndDestroy( rPos-- ); 1755 break; 1756 1757 default: 1758 bRet = sal_False; 1759 } 1760 return bRet; 1761 } 1762 1763 sal_Bool lcl_RejectRedline( SwRedlineTbl& rArr, sal_uInt16& rPos, 1764 sal_Bool bCallDelete, 1765 const SwPosition* pSttRng = 0, 1766 const SwPosition* pEndRng = 0 ) 1767 { 1768 sal_Bool bRet = sal_True; 1769 SwRedline* pRedl = rArr[ rPos ]; 1770 SwPosition *pRStt = 0, *pREnd = 0; 1771 SwComparePosition eCmp = POS_OUTSIDE; 1772 if( pSttRng && pEndRng ) 1773 { 1774 pRStt = pRedl->Start(); 1775 pREnd = pRedl->End(); 1776 eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd ); 1777 } 1778 1779 pRedl->InvalidateRange(); 1780 1781 switch( pRedl->GetType() ) 1782 { 1783 case nsRedlineType_t::REDLINE_INSERT: 1784 { 1785 SwDoc& rDoc = *pRedl->GetDoc(); 1786 const SwPosition *pDelStt = 0, *pDelEnd = 0; 1787 sal_Bool bDelRedl = sal_False; 1788 switch( eCmp ) 1789 { 1790 case POS_INSIDE: 1791 if( bCallDelete ) 1792 { 1793 pDelStt = pSttRng; 1794 pDelEnd = pEndRng; 1795 } 1796 break; 1797 1798 case POS_OVERLAP_BEFORE: 1799 if( bCallDelete ) 1800 { 1801 pDelStt = pRStt; 1802 pDelEnd = pEndRng; 1803 } 1804 break; 1805 case POS_OVERLAP_BEHIND: 1806 if( bCallDelete ) 1807 { 1808 pDelStt = pREnd; 1809 pDelEnd = pSttRng; 1810 } 1811 break; 1812 case POS_OUTSIDE: 1813 case POS_EQUAL: 1814 { 1815 // dann den Bereich wieder loeschen 1816 rArr.Remove( rPos-- ); 1817 bDelRedl = sal_True; 1818 if( bCallDelete ) 1819 { 1820 pDelStt = pRedl->Start(); 1821 pDelEnd = pRedl->End(); 1822 } 1823 } 1824 break; 1825 1826 default: 1827 bRet = sal_False; 1828 } 1829 if( pDelStt && pDelEnd ) 1830 { 1831 SwPaM aPam( *pDelStt, *pDelEnd ); 1832 1833 SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode(); 1834 SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode(); 1835 1836 if( bDelRedl ) 1837 delete pRedl; 1838 1839 RedlineMode_t eOld = rDoc.GetRedlineMode(); 1840 rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE))); 1841 1842 if( pCSttNd && pCEndNd ) 1843 rDoc.DeleteAndJoin( aPam ); 1844 else 1845 { 1846 rDoc.DeleteRange( aPam ); 1847 1848 if( pCSttNd && !pCEndNd ) 1849 { 1850 aPam.GetBound( sal_True ).nContent.Assign( 0, 0 ); 1851 aPam.GetBound( sal_False ).nContent.Assign( 0, 0 ); 1852 aPam.DeleteMark(); 1853 rDoc.DelFullPara( aPam ); 1854 } 1855 } 1856 rDoc.SetRedlineMode_intern( eOld ); 1857 } 1858 else if( bDelRedl ) 1859 delete pRedl; 1860 } 1861 break; 1862 case nsRedlineType_t::REDLINE_DELETE: 1863 { 1864 SwRedline* pNew = 0; 1865 sal_Bool bCheck = sal_False, bReplace = sal_False; 1866 1867 switch( eCmp ) 1868 { 1869 case POS_INSIDE: 1870 { 1871 if( 1 < pRedl->GetStackCount() ) 1872 { 1873 pNew = new SwRedline( *pRedl ); 1874 pNew->PopData(); 1875 } 1876 if( *pSttRng == *pRStt ) 1877 { 1878 pRedl->SetStart( *pEndRng, pRStt ); 1879 bReplace = sal_True; 1880 if( pNew ) 1881 pNew->SetEnd( *pEndRng ); 1882 } 1883 else 1884 { 1885 if( *pEndRng != *pREnd ) 1886 { 1887 // aufsplitten 1888 SwRedline* pCpy = new SwRedline( *pRedl ); 1889 pCpy->SetStart( *pEndRng ); 1890 rArr.Insert( pCpy ); ++rPos; 1891 if( pNew ) 1892 pNew->SetEnd( *pEndRng ); 1893 } 1894 1895 pRedl->SetEnd( *pSttRng, pREnd ); 1896 bCheck = sal_True; 1897 if( pNew ) 1898 pNew->SetStart( *pSttRng ); 1899 } 1900 } 1901 break; 1902 1903 case POS_OVERLAP_BEFORE: 1904 if( 1 < pRedl->GetStackCount() ) 1905 { 1906 pNew = new SwRedline( *pRedl ); 1907 pNew->PopData(); 1908 } 1909 pRedl->SetStart( *pEndRng, pRStt ); 1910 bReplace = sal_True; 1911 if( pNew ) 1912 pNew->SetEnd( *pEndRng ); 1913 break; 1914 1915 case POS_OVERLAP_BEHIND: 1916 if( 1 < pRedl->GetStackCount() ) 1917 { 1918 pNew = new SwRedline( *pRedl ); 1919 pNew->PopData(); 1920 } 1921 pRedl->SetEnd( *pSttRng, pREnd ); 1922 bCheck = sal_True; 1923 if( pNew ) 1924 pNew->SetStart( *pSttRng ); 1925 break; 1926 1927 case POS_OUTSIDE: 1928 case POS_EQUAL: 1929 if( !pRedl->PopData() ) 1930 // das RedlineObject loeschen reicht 1931 rArr.DeleteAndDestroy( rPos-- ); 1932 break; 1933 1934 default: 1935 bRet = sal_False; 1936 } 1937 1938 if( pNew ) 1939 { 1940 rArr.Insert( pNew ); ++rPos; 1941 } 1942 1943 if( bReplace || ( bCheck && !pRedl->HasValidRange() )) 1944 { 1945 // neu einsortieren 1946 rArr.Remove( rArr.GetPos( pRedl )); 1947 rArr.Insert( pRedl ); 1948 } 1949 } 1950 break; 1951 1952 case nsRedlineType_t::REDLINE_FORMAT: 1953 case nsRedlineType_t::REDLINE_FMTCOLL: 1954 { 1955 if( pRedl->GetExtraData() ) 1956 pRedl->GetExtraData()->Reject( *pRedl ); 1957 rArr.DeleteAndDestroy( rPos-- ); 1958 } 1959 break; 1960 1961 default: 1962 bRet = sal_False; 1963 } 1964 return bRet; 1965 } 1966 1967 1968 const SwRedline* lcl_FindCurrRedline( const SwPosition& rSttPos, 1969 sal_uInt16& rPos, 1970 sal_Bool bNext = sal_True ) 1971 { 1972 const SwRedline* pFnd = 0; 1973 const SwRedlineTbl& rArr = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl(); 1974 for( ; rPos < rArr.Count() ; ++rPos ) 1975 { 1976 const SwRedline* pTmp = rArr[ rPos ]; 1977 if( pTmp->HasMark() && pTmp->IsVisible() ) 1978 { 1979 const SwPosition* pRStt = pTmp->Start(), 1980 * pREnd = pRStt == pTmp->GetPoint() ? pTmp->GetMark() 1981 : pTmp->GetPoint(); 1982 if( bNext ? *pRStt <= rSttPos : *pRStt < rSttPos ) 1983 { 1984 if( bNext ? *pREnd > rSttPos : *pREnd >= rSttPos ) 1985 { 1986 pFnd = pTmp; 1987 break; 1988 } 1989 } 1990 else 1991 break; 1992 } 1993 } 1994 return pFnd; 1995 } 1996 1997 // #111827# 1998 int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject, 1999 SwRedlineTbl& rArr, sal_Bool bCallDelete, 2000 const SwPaM& rPam) 2001 { 2002 sal_uInt16 n = 0; 2003 int nCount = 0; // #111827# 2004 2005 const SwPosition* pStt = rPam.Start(), 2006 * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark() 2007 : rPam.GetPoint(); 2008 const SwRedline* pFnd = lcl_FindCurrRedline( *pStt, n, sal_True ); 2009 if( pFnd && // neu ein Teil davon? 2010 ( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd )) 2011 { 2012 // dann nur die TeilSelektion aufheben 2013 if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd )) 2014 nCount++; // #111827# 2015 ++n; 2016 } 2017 2018 for( ; n < rArr.Count(); ++n ) 2019 { 2020 SwRedline* pTmp = rArr[ n ]; 2021 if( pTmp->HasMark() && pTmp->IsVisible() ) 2022 { 2023 if( *pTmp->End() <= *pEnd ) 2024 { 2025 if( (*fn_AcceptReject)( rArr, n, bCallDelete, 0, 0 )) 2026 nCount++; // #111827# 2027 } 2028 else 2029 { 2030 if( *pTmp->Start() < *pEnd ) 2031 { 2032 // dann nur in der TeilSelektion aufheben 2033 if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd )) 2034 nCount++; // #111827# 2035 } 2036 break; 2037 } 2038 } 2039 } 2040 return nCount; // #111827# 2041 } 2042 2043 void lcl_AdjustRedlineRange( SwPaM& rPam ) 2044 { 2045 // die Selektion steht nur im ContentBereich. Wenn es aber Redlines 2046 // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die 2047 // die Selection auf diese 2048 SwPosition* pStt = rPam.Start(), 2049 * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark() 2050 : rPam.GetPoint(); 2051 SwDoc* pDoc = rPam.GetDoc(); 2052 if( !pStt->nContent.GetIndex() && 2053 !pDoc->GetNodes()[ pStt->nNode.GetIndex() - 1 ]->IsCntntNode() ) 2054 { 2055 const SwRedline* pRedl = pDoc->GetRedline( *pStt, 0 ); 2056 if( pRedl ) 2057 { 2058 const SwPosition* pRStt = pRedl->Start(); 2059 if( !pRStt->nContent.GetIndex() && pRStt->nNode.GetIndex() == 2060 pStt->nNode.GetIndex() - 1 ) 2061 *pStt = *pRStt; 2062 } 2063 } 2064 if( pEnd->nNode.GetNode().IsCntntNode() && 2065 !pDoc->GetNodes()[ pEnd->nNode.GetIndex() + 1 ]->IsCntntNode() && 2066 pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() ) 2067 { 2068 const SwRedline* pRedl = pDoc->GetRedline( *pEnd, 0 ); 2069 if( pRedl ) 2070 { 2071 const SwPosition* pREnd = pRedl->End(); 2072 if( !pREnd->nContent.GetIndex() && pREnd->nNode.GetIndex() == 2073 pEnd->nNode.GetIndex() + 1 ) 2074 *pEnd = *pREnd; 2075 } 2076 } 2077 } 2078 2079 2080 bool SwDoc::AcceptRedline( sal_uInt16 nPos, bool bCallDelete ) 2081 { 2082 sal_Bool bRet = sal_False; 2083 2084 // aufjedenfall auf sichtbar umschalten 2085 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) != 2086 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) ) 2087 SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode)); 2088 2089 SwRedline* pTmp = (*pRedlineTbl)[ nPos ]; 2090 if( pTmp->HasMark() && pTmp->IsVisible() ) 2091 { 2092 if (GetIDocumentUndoRedo().DoesUndo()) 2093 { 2094 // #111827# 2095 SwRewriter aRewriter; 2096 2097 aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr()); 2098 GetIDocumentUndoRedo().StartUndo(UNDO_ACCEPT_REDLINE, &aRewriter); 2099 } 2100 2101 int nLoopCnt = 2; 2102 sal_uInt16 nSeqNo = pTmp->GetSeqNo(); 2103 2104 do { 2105 2106 if (GetIDocumentUndoRedo().DoesUndo()) 2107 { 2108 SwUndo *const pUndo( new SwUndoAcceptRedline(*pTmp) ); 2109 GetIDocumentUndoRedo().AppendUndo(pUndo); 2110 } 2111 2112 bRet |= lcl_AcceptRedline( *pRedlineTbl, nPos, bCallDelete ); 2113 2114 if( nSeqNo ) 2115 { 2116 if( USHRT_MAX == nPos ) 2117 nPos = 0; 2118 sal_uInt16 nFndPos = 2 == nLoopCnt 2119 ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos ) 2120 : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ); 2121 if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) && 2122 USHRT_MAX != ( nFndPos = 2123 pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) ) 2124 pTmp = (*pRedlineTbl)[ nPos = nFndPos ]; 2125 else 2126 nLoopCnt = 0; 2127 } 2128 else 2129 nLoopCnt = 0; 2130 2131 } while( nLoopCnt ); 2132 2133 if( bRet ) 2134 { 2135 CompressRedlines(); 2136 SetModified(); 2137 } 2138 2139 if (GetIDocumentUndoRedo().DoesUndo()) 2140 { 2141 GetIDocumentUndoRedo().EndUndo(UNDO_END, 0); 2142 } 2143 } 2144 return bRet; 2145 } 2146 2147 bool SwDoc::AcceptRedline( const SwPaM& rPam, bool bCallDelete ) 2148 { 2149 // aufjedenfall auf sichtbar umschalten 2150 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) != 2151 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) ) 2152 SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode)); 2153 2154 // die Selektion steht nur im ContentBereich. Wenn es aber Redlines 2155 // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die 2156 // die Selection auf diese 2157 SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() ); 2158 lcl_AdjustRedlineRange( aPam ); 2159 2160 if (GetIDocumentUndoRedo().DoesUndo()) 2161 { 2162 GetIDocumentUndoRedo().StartUndo( UNDO_ACCEPT_REDLINE, NULL ); 2163 GetIDocumentUndoRedo().AppendUndo( new SwUndoAcceptRedline( aPam )); 2164 } 2165 2166 // #111827# 2167 int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *pRedlineTbl, 2168 bCallDelete, aPam ); 2169 if( nRet > 0 ) 2170 { 2171 CompressRedlines(); 2172 SetModified(); 2173 } 2174 if (GetIDocumentUndoRedo().DoesUndo()) 2175 { 2176 // #111827# 2177 String aTmpStr; 2178 2179 { 2180 SwRewriter aRewriter; 2181 aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet)); 2182 aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES))); 2183 } 2184 2185 SwRewriter aRewriter; 2186 aRewriter.AddRule(UNDO_ARG1, aTmpStr); 2187 2188 GetIDocumentUndoRedo().EndUndo( UNDO_ACCEPT_REDLINE, &aRewriter ); 2189 } 2190 return nRet != 0; 2191 } 2192 2193 bool SwDoc::RejectRedline( sal_uInt16 nPos, bool bCallDelete ) 2194 { 2195 sal_Bool bRet = sal_False; 2196 2197 // aufjedenfall auf sichtbar umschalten 2198 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) != 2199 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) ) 2200 SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode)); 2201 2202 SwRedline* pTmp = (*pRedlineTbl)[ nPos ]; 2203 if( pTmp->HasMark() && pTmp->IsVisible() ) 2204 { 2205 if (GetIDocumentUndoRedo().DoesUndo()) 2206 { 2207 // #111827# 2208 SwRewriter aRewriter; 2209 2210 aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr()); 2211 GetIDocumentUndoRedo().StartUndo(UNDO_REJECT_REDLINE, &aRewriter); 2212 } 2213 2214 int nLoopCnt = 2; 2215 sal_uInt16 nSeqNo = pTmp->GetSeqNo(); 2216 2217 do { 2218 2219 if (GetIDocumentUndoRedo().DoesUndo()) 2220 { 2221 SwUndo *const pUndo( new SwUndoRejectRedline( *pTmp ) ); 2222 GetIDocumentUndoRedo().AppendUndo(pUndo); 2223 } 2224 2225 bRet |= lcl_RejectRedline( *pRedlineTbl, nPos, bCallDelete ); 2226 2227 if( nSeqNo ) 2228 { 2229 if( USHRT_MAX == nPos ) 2230 nPos = 0; 2231 sal_uInt16 nFndPos = 2 == nLoopCnt 2232 ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos ) 2233 : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ); 2234 if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) && 2235 USHRT_MAX != ( nFndPos = 2236 pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) ) 2237 pTmp = (*pRedlineTbl)[ nPos = nFndPos ]; 2238 else 2239 nLoopCnt = 0; 2240 } 2241 else 2242 nLoopCnt = 0; 2243 2244 } while( nLoopCnt ); 2245 2246 if( bRet ) 2247 { 2248 CompressRedlines(); 2249 SetModified(); 2250 } 2251 2252 if (GetIDocumentUndoRedo().DoesUndo()) 2253 { 2254 GetIDocumentUndoRedo().EndUndo(UNDO_END, 0); 2255 } 2256 } 2257 return bRet; 2258 } 2259 2260 bool SwDoc::RejectRedline( const SwPaM& rPam, bool bCallDelete ) 2261 { 2262 // aufjedenfall auf sichtbar umschalten 2263 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) != 2264 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) ) 2265 SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode)); 2266 2267 // die Selektion steht nur im ContentBereich. Wenn es aber Redlines 2268 // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die 2269 // die Selection auf diese 2270 SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() ); 2271 lcl_AdjustRedlineRange( aPam ); 2272 2273 if (GetIDocumentUndoRedo().DoesUndo()) 2274 { 2275 GetIDocumentUndoRedo().StartUndo( UNDO_REJECT_REDLINE, NULL ); 2276 GetIDocumentUndoRedo().AppendUndo( new SwUndoRejectRedline(aPam) ); 2277 } 2278 2279 // #111827# 2280 int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *pRedlineTbl, 2281 bCallDelete, aPam ); 2282 if( nRet > 0 ) 2283 { 2284 CompressRedlines(); 2285 SetModified(); 2286 } 2287 if (GetIDocumentUndoRedo().DoesUndo()) 2288 { 2289 // #111827# 2290 String aTmpStr; 2291 2292 { 2293 SwRewriter aRewriter; 2294 aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet)); 2295 aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES))); 2296 } 2297 2298 SwRewriter aRewriter; 2299 aRewriter.AddRule(UNDO_ARG1, aTmpStr); 2300 2301 GetIDocumentUndoRedo().EndUndo( UNDO_REJECT_REDLINE, &aRewriter ); 2302 } 2303 2304 return nRet != 0; 2305 } 2306 2307 const SwRedline* SwDoc::SelNextRedline( SwPaM& rPam ) const 2308 { 2309 rPam.DeleteMark(); 2310 rPam.SetMark(); 2311 2312 SwPosition& rSttPos = *rPam.GetPoint(); 2313 SwPosition aSavePos( rSttPos ); 2314 sal_Bool bRestart; 2315 2316 // sollte die StartPos auf dem letzen gueligen ContentNode stehen, 2317 // dann aufjedenfall das naechste Redline nehmen 2318 sal_uInt16 n = 0; 2319 const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_True ); 2320 if( pFnd ) 2321 { 2322 const SwPosition* pEnd = pFnd->End(); 2323 if( !pEnd->nNode.GetNode().IsCntntNode() ) 2324 { 2325 SwNodeIndex aTmp( pEnd->nNode ); 2326 SwCntntNode* pCNd = GetNodes().GoPrevSection( &aTmp ); 2327 if( !pCNd || ( aTmp == rSttPos.nNode && 2328 pCNd->Len() == rSttPos.nContent.GetIndex() )) 2329 pFnd = 0; 2330 } 2331 if( pFnd ) 2332 rSttPos = *pFnd->End(); 2333 } 2334 2335 do { 2336 bRestart = sal_False; 2337 2338 for( ; !pFnd && n < pRedlineTbl->Count(); ++n ) 2339 { 2340 pFnd = (*pRedlineTbl)[ n ]; 2341 if( pFnd->HasMark() && pFnd->IsVisible() ) 2342 { 2343 *rPam.GetMark() = *pFnd->Start(); 2344 rSttPos = *pFnd->End(); 2345 break; 2346 } 2347 else 2348 pFnd = 0; 2349 } 2350 2351 if( pFnd ) 2352 { 2353 // alle vom gleichen Typ und Author, die hinter einander liegen 2354 // zu einer Selektion zusammenfassen. 2355 const SwPosition* pPrevEnd = pFnd->End(); 2356 while( ++n < pRedlineTbl->Count() ) 2357 { 2358 const SwRedline* pTmp = (*pRedlineTbl)[ n ]; 2359 if( pTmp->HasMark() && pTmp->IsVisible() ) 2360 { 2361 const SwPosition *pRStt; 2362 if( pFnd->GetType() == pTmp->GetType() && 2363 pFnd->GetAuthor() == pTmp->GetAuthor() && 2364 ( *pPrevEnd == *( pRStt = pTmp->Start() ) || 2365 IsPrevPos( *pPrevEnd, *pRStt )) ) 2366 { 2367 pPrevEnd = pTmp->End(); 2368 rSttPos = *pPrevEnd; 2369 } 2370 else 2371 break; 2372 } 2373 } 2374 } 2375 2376 if( pFnd ) 2377 { 2378 const SwRedline* pSaveFnd = pFnd; 2379 2380 SwCntntNode* pCNd; 2381 SwNodeIndex* pIdx = &rPam.GetMark()->nNode; 2382 if( !pIdx->GetNode().IsCntntNode() && 2383 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) ) 2384 { 2385 if( *pIdx <= rPam.GetPoint()->nNode ) 2386 rPam.GetMark()->nContent.Assign( pCNd, 0 ); 2387 else 2388 pFnd = 0; 2389 } 2390 2391 if( pFnd ) 2392 { 2393 pIdx = &rPam.GetPoint()->nNode; 2394 if( !pIdx->GetNode().IsCntntNode() && 2395 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) ) 2396 { 2397 if( *pIdx >= rPam.GetMark()->nNode ) 2398 rPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); 2399 else 2400 pFnd = 0; 2401 } 2402 } 2403 2404 if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() ) 2405 { 2406 if( n < pRedlineTbl->Count() ) 2407 { 2408 bRestart = sal_True; 2409 *rPam.GetPoint() = *pSaveFnd->End(); 2410 } 2411 else 2412 { 2413 rPam.DeleteMark(); 2414 *rPam.GetPoint() = aSavePos; 2415 } 2416 pFnd = 0; 2417 } 2418 } 2419 } while( bRestart ); 2420 2421 return pFnd; 2422 } 2423 2424 const SwRedline* SwDoc::SelPrevRedline( SwPaM& rPam ) const 2425 { 2426 rPam.DeleteMark(); 2427 rPam.SetMark(); 2428 2429 SwPosition& rSttPos = *rPam.GetPoint(); 2430 SwPosition aSavePos( rSttPos ); 2431 sal_Bool bRestart; 2432 2433 // sollte die StartPos auf dem ersten gueligen ContentNode stehen, 2434 // dann aufjedenfall das vorherige Redline nehmen 2435 sal_uInt16 n = 0; 2436 const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_False ); 2437 if( pFnd ) 2438 { 2439 const SwPosition* pStt = pFnd->Start(); 2440 if( !pStt->nNode.GetNode().IsCntntNode() ) 2441 { 2442 SwNodeIndex aTmp( pStt->nNode ); 2443 SwCntntNode* pCNd = GetNodes().GoNextSection( &aTmp ); 2444 if( !pCNd || ( aTmp == rSttPos.nNode && 2445 !rSttPos.nContent.GetIndex() )) 2446 pFnd = 0; 2447 } 2448 if( pFnd ) 2449 rSttPos = *pFnd->Start(); 2450 } 2451 2452 do { 2453 bRestart = sal_False; 2454 2455 while( !pFnd && 0 < n ) 2456 { 2457 pFnd = (*pRedlineTbl)[ --n ]; 2458 if( pFnd->HasMark() && pFnd->IsVisible() ) 2459 { 2460 *rPam.GetMark() = *pFnd->End(); 2461 rSttPos = *pFnd->Start(); 2462 } 2463 else 2464 pFnd = 0; 2465 } 2466 2467 if( pFnd ) 2468 { 2469 // alle vom gleichen Typ und Author, die hinter einander liegen 2470 // zu einer Selektion zusammenfassen. 2471 const SwPosition* pNextStt = pFnd->Start(); 2472 while( 0 < n ) 2473 { 2474 const SwRedline* pTmp = (*pRedlineTbl)[ --n ]; 2475 if( pTmp->HasMark() && pTmp->IsVisible() ) 2476 { 2477 const SwPosition *pREnd; 2478 if( pFnd->GetType() == pTmp->GetType() && 2479 pFnd->GetAuthor() == pTmp->GetAuthor() && 2480 ( *pNextStt == *( pREnd = pTmp->End() ) || 2481 IsPrevPos( *pREnd, *pNextStt )) ) 2482 { 2483 pNextStt = pTmp->Start(); 2484 rSttPos = *pNextStt; 2485 } 2486 else 2487 { 2488 ++n; 2489 break; 2490 } 2491 } 2492 } 2493 } 2494 2495 if( pFnd ) 2496 { 2497 const SwRedline* pSaveFnd = pFnd; 2498 2499 SwCntntNode* pCNd; 2500 SwNodeIndex* pIdx = &rPam.GetMark()->nNode; 2501 if( !pIdx->GetNode().IsCntntNode() && 2502 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) ) 2503 { 2504 if( *pIdx >= rPam.GetPoint()->nNode ) 2505 rPam.GetMark()->nContent.Assign( pCNd, pCNd->Len() ); 2506 else 2507 pFnd = 0; 2508 } 2509 2510 if( pFnd ) 2511 { 2512 pIdx = &rPam.GetPoint()->nNode; 2513 if( !pIdx->GetNode().IsCntntNode() && 2514 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) ) 2515 { 2516 if( *pIdx <= rPam.GetMark()->nNode ) 2517 rPam.GetPoint()->nContent.Assign( pCNd, 0 ); 2518 else 2519 pFnd = 0; 2520 } 2521 } 2522 2523 if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() ) 2524 { 2525 if( n ) 2526 { 2527 bRestart = sal_True; 2528 *rPam.GetPoint() = *pSaveFnd->Start(); 2529 } 2530 else 2531 { 2532 rPam.DeleteMark(); 2533 *rPam.GetPoint() = aSavePos; 2534 } 2535 pFnd = 0; 2536 } 2537 } 2538 } while( bRestart ); 2539 2540 return pFnd; 2541 } 2542 2543 // Kommentar am Redline setzen 2544 bool SwDoc::SetRedlineComment( const SwPaM& rPaM, const String& rS ) 2545 { 2546 sal_Bool bRet = sal_False; 2547 const SwPosition* pStt = rPaM.Start(), 2548 * pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark() 2549 : rPaM.GetPoint(); 2550 sal_uInt16 n = 0; 2551 if( lcl_FindCurrRedline( *pStt, n, sal_True ) ) 2552 { 2553 for( ; n < pRedlineTbl->Count(); ++n ) 2554 { 2555 bRet = sal_True; 2556 SwRedline* pTmp = (*pRedlineTbl)[ n ]; 2557 if( pStt != pEnd && *pTmp->Start() > *pEnd ) 2558 break; 2559 2560 pTmp->SetComment( rS ); 2561 if( *pTmp->End() >= *pEnd ) 2562 break; 2563 } 2564 } 2565 if( bRet ) 2566 SetModified(); 2567 2568 return bRet; 2569 } 2570 2571 // legt gebenenfalls einen neuen Author an 2572 sal_uInt16 SwDoc::GetRedlineAuthor() 2573 { 2574 return SW_MOD()->GetRedlineAuthor(); 2575 } 2576 2577 // fuer die Reader usw. - neuen Author in die Tabelle eintragen 2578 sal_uInt16 SwDoc::InsertRedlineAuthor( const String& rNew ) 2579 { 2580 return SW_MOD()->InsertRedlineAuthor(rNew); 2581 } 2582 2583 void SwDoc::UpdateRedlineAttr() 2584 { 2585 const SwRedlineTbl& rTbl = GetRedlineTbl(); 2586 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 2587 { 2588 SwRedline* pRedl = rTbl[ n ]; 2589 if( pRedl->IsVisible() ) 2590 pRedl->InvalidateRange(); 2591 } 2592 } 2593 2594 // setze Kommentar-Text fuers Redline, das dann per AppendRedline 2595 // hereinkommt. Wird vom Autoformat benutzt. 0-Pointer setzt den Modus 2596 // wieder zurueck. Pointer wird nicht kopiert, muss also gueltig bleiben! 2597 void SwDoc::SetAutoFmtRedlineComment( const String* pTxt, sal_uInt16 nSeqNo ) 2598 { 2599 mbIsAutoFmtRedline = 0 != pTxt; 2600 if( pTxt ) 2601 { 2602 if( !pAutoFmtRedlnComment ) 2603 pAutoFmtRedlnComment = new String( *pTxt ); 2604 else 2605 *pAutoFmtRedlnComment = *pTxt; 2606 } 2607 else if( pAutoFmtRedlnComment ) 2608 delete pAutoFmtRedlnComment, pAutoFmtRedlnComment = 0; 2609 2610 nAutoFmtRedlnCommentNo = nSeqNo; 2611 } 2612 2613 void SwDoc::SetRedlinePassword( 2614 /*[in]*/const uno::Sequence <sal_Int8>& rNewPassword) 2615 { 2616 aRedlinePasswd = rNewPassword; 2617 SetModified(); 2618 } 2619 2620 /* */ 2621 2622 sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_Bool bIns ) 2623 { 2624 sal_Bool bRet = sal_False; 2625 if( p->HasValidRange() ) 2626 { 2627 bRet = _SwRedlineTbl::Insert( p ); 2628 p->CallDisplayFunc(); 2629 } 2630 else if( bIns ) 2631 bRet = InsertWithValidRanges( p ); 2632 else 2633 { 2634 ASSERT( !this, "Redline: falscher Bereich" ); 2635 } 2636 return bRet; 2637 } 2638 2639 sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_uInt16& rP, sal_Bool bIns ) 2640 { 2641 sal_Bool bRet = sal_False; 2642 if( p->HasValidRange() ) 2643 { 2644 bRet = _SwRedlineTbl::Insert( p, rP ); 2645 p->CallDisplayFunc(); 2646 } 2647 else if( bIns ) 2648 bRet = InsertWithValidRanges( p, &rP ); 2649 else 2650 { 2651 ASSERT( !this, "Redline: falscher Bereich" ); 2652 } 2653 return bRet; 2654 } 2655 2656 sal_Bool SwRedlineTbl::InsertWithValidRanges( SwRedlinePtr& p, sal_uInt16* pInsPos ) 2657 { 2658 // erzeuge aus den Selektion gueltige "Teilbereiche". 2659 sal_Bool bAnyIns = sal_False; 2660 SwPosition* pStt = p->Start(), 2661 * pEnd = pStt == p->GetPoint() ? p->GetMark() : p->GetPoint(); 2662 SwPosition aNewStt( *pStt ); 2663 SwNodes& rNds = aNewStt.nNode.GetNodes(); 2664 SwCntntNode* pC; 2665 2666 if( !aNewStt.nNode.GetNode().IsCntntNode() ) 2667 { 2668 pC = rNds.GoNext( &aNewStt.nNode ); 2669 if( pC ) 2670 aNewStt.nContent.Assign( pC, 0 ); 2671 else 2672 aNewStt.nNode = rNds.GetEndOfContent(); 2673 } 2674 2675 SwRedline* pNew = 0; 2676 sal_uInt16 nInsPos; 2677 2678 if( aNewStt < *pEnd ) 2679 do { 2680 if( !pNew ) 2681 pNew = new SwRedline( p->GetRedlineData(), aNewStt ); 2682 else 2683 { 2684 pNew->DeleteMark(); 2685 *pNew->GetPoint() = aNewStt; 2686 } 2687 2688 pNew->SetMark(); 2689 GoEndSection( pNew->GetPoint() ); 2690 // i60396: If the redlines starts before a table but the table is the last member 2691 // of the section, the GoEndSection will end inside the table. 2692 // This will result in an incorrect redline, so we've to go back 2693 SwNode* pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode(); 2694 // We end in a table when pTab != 0 2695 if( pTab && !pNew->GetMark()->nNode.GetNode().StartOfSectionNode()->FindTableNode() ) 2696 { // but our Mark was outside the table => Correction 2697 do 2698 { 2699 // We want to be before the table 2700 *pNew->GetPoint() = SwPosition(*pTab); 2701 pC = GoPreviousNds( &pNew->GetPoint()->nNode, sal_False ); // here we are. 2702 if( pC ) 2703 pNew->GetPoint()->nContent.Assign( pC, 0 ); 2704 pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode(); 2705 }while( pTab ); // If there is another table we have to repeat our step backwards 2706 } 2707 2708 if( *pNew->GetPoint() > *pEnd ) 2709 { 2710 pC = 0; 2711 if( aNewStt.nNode != pEnd->nNode ) 2712 do { 2713 SwNode& rCurNd = aNewStt.nNode.GetNode(); 2714 if( rCurNd.IsStartNode() ) 2715 { 2716 if( rCurNd.EndOfSectionIndex() < pEnd->nNode.GetIndex() ) 2717 aNewStt.nNode = *rCurNd.EndOfSectionNode(); 2718 else 2719 break; 2720 } 2721 else if( rCurNd.IsCntntNode() ) 2722 pC = rCurNd.GetCntntNode(); 2723 aNewStt.nNode++; 2724 } while( aNewStt.nNode.GetIndex() < pEnd->nNode.GetIndex() ); 2725 2726 if( aNewStt.nNode == pEnd->nNode ) 2727 aNewStt.nContent = pEnd->nContent; 2728 else if( pC ) 2729 { 2730 aNewStt.nNode = *pC; 2731 aNewStt.nContent.Assign( pC, pC->Len() ); 2732 } 2733 2734 if( aNewStt <= *pEnd ) 2735 *pNew->GetPoint() = aNewStt; 2736 } 2737 else 2738 aNewStt = *pNew->GetPoint(); 2739 #ifdef DEBUG 2740 CheckPosition( pNew->GetPoint(), pNew->GetMark() ); 2741 #endif 2742 if( *pNew->GetPoint() != *pNew->GetMark() && 2743 _SwRedlineTbl::Insert( pNew, nInsPos ) ) 2744 { 2745 pNew->CallDisplayFunc(); 2746 bAnyIns = sal_True; 2747 pNew = 0; 2748 if( pInsPos && *pInsPos < nInsPos ) 2749 *pInsPos = nInsPos; 2750 } 2751 2752 if( aNewStt >= *pEnd || 2753 0 == (pC = rNds.GoNext( &aNewStt.nNode )) ) 2754 break; 2755 2756 aNewStt.nContent.Assign( pC, 0 ); 2757 2758 } while( aNewStt < *pEnd ); 2759 2760 delete pNew; 2761 delete p, p = 0; 2762 return bAnyIns; 2763 } 2764 2765 void SwRedlineTbl::Remove( sal_uInt16 nP, sal_uInt16 nL ) 2766 { 2767 SwDoc* pDoc = 0; 2768 if( !nP && nL && nL == _SwRedlineTbl::Count() ) 2769 pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc(); 2770 2771 _SwRedlineTbl::Remove( nP, nL ); 2772 2773 ViewShell* pSh; 2774 if( pDoc && !pDoc->IsInDtor() && 2775 0 != ( pSh = pDoc->GetCurrentViewShell()) ) //swmod 071108//swmod 071225 2776 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) ); 2777 } 2778 2779 void SwRedlineTbl::DeleteAndDestroy( sal_uInt16 nP, sal_uInt16 nL ) 2780 { 2781 SwDoc* pDoc = 0; 2782 if( !nP && nL && nL == _SwRedlineTbl::Count() ) 2783 pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc(); 2784 2785 _SwRedlineTbl::DeleteAndDestroy( nP, nL ); 2786 2787 ViewShell* pSh; 2788 if( pDoc && !pDoc->IsInDtor() && 2789 0 != ( pSh = pDoc->GetCurrentViewShell() ) ) //swmod 071108//swmod 071225 2790 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) ); 2791 } 2792 2793 // suche den naechsten oder vorherigen Redline mit dergleichen Seq.No 2794 // Mit dem Lookahead kann die Suche eingeschraenkt werden. 0 oder 2795 // USHRT_MAX suchen im gesamten Array. 2796 sal_uInt16 SwRedlineTbl::FindNextOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const 2797 { 2798 return nSttPos + 1 < _SwRedlineTbl::Count() 2799 ? FindNextSeqNo( _SwRedlineTbl::GetObject( nSttPos ) 2800 ->GetSeqNo(), nSttPos+1, nLookahead ) 2801 : USHRT_MAX; 2802 } 2803 2804 sal_uInt16 SwRedlineTbl::FindPrevOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const 2805 { 2806 return nSttPos ? FindPrevSeqNo( _SwRedlineTbl::GetObject( 2807 nSttPos )->GetSeqNo(), 2808 nSttPos-1, nLookahead ) 2809 : USHRT_MAX; 2810 } 2811 2812 sal_uInt16 SwRedlineTbl::FindNextSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos, 2813 sal_uInt16 nLookahead ) const 2814 { 2815 sal_uInt16 nRet = USHRT_MAX, nEnd; 2816 if( nSeqNo && nSttPos < _SwRedlineTbl::Count() ) 2817 { 2818 nEnd = _SwRedlineTbl::Count(); 2819 if( nLookahead && USHRT_MAX != nLookahead && 2820 nSttPos + nLookahead < _SwRedlineTbl::Count() ) 2821 nEnd = nSttPos + nLookahead; 2822 2823 for( ; nSttPos < nEnd; ++nSttPos ) 2824 if( nSeqNo == _SwRedlineTbl::GetObject( nSttPos )->GetSeqNo() ) 2825 { 2826 nRet = nSttPos; 2827 break; 2828 } 2829 } 2830 return nRet; 2831 } 2832 2833 sal_uInt16 SwRedlineTbl::FindPrevSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos, 2834 sal_uInt16 nLookahead ) const 2835 { 2836 sal_uInt16 nRet = USHRT_MAX, nEnd; 2837 if( nSeqNo && nSttPos < _SwRedlineTbl::Count() ) 2838 { 2839 nEnd = 0; 2840 if( nLookahead && USHRT_MAX != nLookahead && nSttPos > nLookahead ) 2841 nEnd = nSttPos - nLookahead; 2842 2843 ++nSttPos; 2844 while( nSttPos > nEnd ) 2845 if( nSeqNo == _SwRedlineTbl::GetObject( --nSttPos )->GetSeqNo() ) 2846 { 2847 nRet = nSttPos; 2848 break; 2849 } 2850 } 2851 return nRet; 2852 } 2853 2854 /* */ 2855 2856 SwRedlineExtraData::~SwRedlineExtraData() 2857 { 2858 } 2859 2860 void SwRedlineExtraData::Accept( SwPaM& ) const 2861 { 2862 } 2863 2864 void SwRedlineExtraData::Reject( SwPaM& ) const 2865 { 2866 } 2867 2868 int SwRedlineExtraData::operator == ( const SwRedlineExtraData& ) const 2869 { 2870 return sal_False; 2871 } 2872 2873 2874 SwRedlineExtraData_FmtColl::SwRedlineExtraData_FmtColl( const String& rColl, 2875 sal_uInt16 nPoolFmtId, 2876 const SfxItemSet* pItemSet ) 2877 : sFmtNm(rColl), pSet(0), nPoolId(nPoolFmtId) 2878 { 2879 if( pItemSet && pItemSet->Count() ) 2880 pSet = new SfxItemSet( *pItemSet ); 2881 } 2882 2883 SwRedlineExtraData_FmtColl::~SwRedlineExtraData_FmtColl() 2884 { 2885 delete pSet; 2886 } 2887 2888 SwRedlineExtraData* SwRedlineExtraData_FmtColl::CreateNew() const 2889 { 2890 return new SwRedlineExtraData_FmtColl( sFmtNm, nPoolId, pSet ); 2891 } 2892 2893 void SwRedlineExtraData_FmtColl::Reject( SwPaM& rPam ) const 2894 { 2895 SwDoc* pDoc = rPam.GetDoc(); 2896 2897 // was ist mit Undo ? ist das abgeschaltet ?? 2898 SwTxtFmtColl* pColl = USHRT_MAX == nPoolId 2899 ? pDoc->FindTxtFmtCollByName( sFmtNm ) 2900 : pDoc->GetTxtCollFromPool( nPoolId ); 2901 if( pColl ) 2902 pDoc->SetTxtFmtColl( rPam, pColl, false ); 2903 2904 if( pSet ) 2905 { 2906 rPam.SetMark(); 2907 SwPosition& rMark = *rPam.GetMark(); 2908 SwTxtNode* pTNd = rMark.nNode.GetNode().GetTxtNode(); 2909 if( pTNd ) 2910 { 2911 rMark.nContent.Assign( pTNd, pTNd->GetTxt().Len() ); 2912 2913 if( pTNd->HasSwAttrSet() ) 2914 { 2915 // nur die setzen, die nicht mehr vorhanden sind. Andere 2916 // koennen jetzt veraendert drin stehen, aber die werden 2917 // nicht angefasst. 2918 SfxItemSet aTmp( *pSet ); 2919 aTmp.Differentiate( *pTNd->GetpSwAttrSet() ); 2920 pDoc->InsertItemSet( rPam, aTmp, 0 ); 2921 } 2922 else 2923 { 2924 pDoc->InsertItemSet( rPam, *pSet, 0 ); 2925 } 2926 } 2927 rPam.DeleteMark(); 2928 } 2929 } 2930 2931 int SwRedlineExtraData_FmtColl::operator == ( const SwRedlineExtraData& r) const 2932 { 2933 const SwRedlineExtraData_FmtColl& rCmp = (SwRedlineExtraData_FmtColl&)r; 2934 return sFmtNm == rCmp.sFmtNm && nPoolId == rCmp.nPoolId && 2935 ( ( !pSet && !rCmp.pSet ) || 2936 ( pSet && rCmp.pSet && *pSet == *rCmp.pSet ) ); 2937 } 2938 2939 void SwRedlineExtraData_FmtColl::SetItemSet( const SfxItemSet& rSet ) 2940 { 2941 delete pSet; 2942 if( rSet.Count() ) 2943 pSet = new SfxItemSet( rSet ); 2944 else 2945 pSet = 0; 2946 } 2947 2948 2949 SwRedlineExtraData_Format::SwRedlineExtraData_Format( const SfxItemSet& rSet ) 2950 { 2951 SfxItemIter aIter( rSet ); 2952 const SfxPoolItem* pItem = aIter.FirstItem(); 2953 while( sal_True ) 2954 { 2955 aWhichIds.Insert( pItem->Which(), aWhichIds.Count() ); 2956 if( aIter.IsAtEnd() ) 2957 break; 2958 pItem = aIter.NextItem(); 2959 } 2960 } 2961 2962 SwRedlineExtraData_Format::SwRedlineExtraData_Format( 2963 const SwRedlineExtraData_Format& rCpy ) 2964 : SwRedlineExtraData(), aWhichIds( (sal_uInt8)rCpy.aWhichIds.Count() ) 2965 { 2966 aWhichIds.Insert( &rCpy.aWhichIds, 0 ); 2967 } 2968 2969 SwRedlineExtraData_Format::~SwRedlineExtraData_Format() 2970 { 2971 } 2972 2973 SwRedlineExtraData* SwRedlineExtraData_Format::CreateNew() const 2974 { 2975 return new SwRedlineExtraData_Format( *this ); 2976 } 2977 2978 void SwRedlineExtraData_Format::Reject( SwPaM& rPam ) const 2979 { 2980 SwDoc* pDoc = rPam.GetDoc(); 2981 2982 RedlineMode_t eOld = pDoc->GetRedlineMode(); 2983 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE))); 2984 2985 // eigentlich muesste hier das Attribut zurueck gesetzt werden!!! 2986 for( sal_uInt16 n = 0, nEnd = aWhichIds.Count(); n < nEnd; ++n ) 2987 { 2988 pDoc->InsertPoolItem( rPam, *GetDfltAttr( aWhichIds[ n ] ), 2989 nsSetAttrMode::SETATTR_DONTEXPAND ); 2990 } 2991 2992 pDoc->SetRedlineMode_intern( eOld ); 2993 } 2994 2995 int SwRedlineExtraData_Format::operator == ( const SwRedlineExtraData& rCmp ) const 2996 { 2997 int nRet = 1; 2998 sal_uInt16 n = 0, nEnd = aWhichIds.Count(); 2999 if( nEnd != ((SwRedlineExtraData_Format&)rCmp).aWhichIds.Count() ) 3000 nRet = 0; 3001 else 3002 for( ; n < nEnd; ++n ) 3003 if( ((SwRedlineExtraData_Format&)rCmp).aWhichIds[n] != aWhichIds[n]) 3004 { 3005 nRet = 0; 3006 break; 3007 } 3008 return nRet; 3009 } 3010 3011 /* */ 3012 3013 SwRedlineData::SwRedlineData( RedlineType_t eT, sal_uInt16 nAut ) 3014 : pNext( 0 ), pExtraData( 0 ), eType( eT ), nAuthor( nAut ), nSeqNo( 0 ) 3015 { 3016 aStamp.SetSec( 0 ); 3017 aStamp.Set100Sec( 0 ); 3018 } 3019 3020 SwRedlineData::SwRedlineData( const SwRedlineData& rCpy, sal_Bool bCpyNext ) 3021 : 3022 pNext( (bCpyNext && rCpy.pNext) ? new SwRedlineData( *rCpy.pNext ) : 0 ), 3023 pExtraData( rCpy.pExtraData ? rCpy.pExtraData->CreateNew() : 0 ), 3024 sComment( rCpy.sComment ), aStamp( rCpy.aStamp ), eType( rCpy.eType ), 3025 nAuthor( rCpy.nAuthor ), nSeqNo( rCpy.nSeqNo ) 3026 { 3027 } 3028 3029 // fuer sw3io: pNext geht in eigenen Besitz ueber! 3030 SwRedlineData::SwRedlineData(RedlineType_t eT, sal_uInt16 nAut, const DateTime& rDT, 3031 const String& rCmnt, SwRedlineData *pNxt, SwRedlineExtraData* pData) 3032 : pNext(pNxt), pExtraData(pData), sComment(rCmnt), aStamp(rDT), 3033 eType(eT), nAuthor(nAut), nSeqNo(0) 3034 { 3035 } 3036 3037 SwRedlineData::~SwRedlineData() 3038 { 3039 delete pExtraData; 3040 delete pNext; 3041 } 3042 3043 // ExtraData wird kopiert, der Pointer geht also NICHT in den Besitz 3044 // des RedlineObjectes! 3045 void SwRedlineData::SetExtraData( const SwRedlineExtraData* pData ) 3046 { 3047 delete pExtraData; 3048 3049 if( pData ) 3050 pExtraData = pData->CreateNew(); 3051 else 3052 pExtraData = 0; 3053 } 3054 3055 // #111827# 3056 String SwRedlineData::GetDescr() const 3057 { 3058 String aResult; 3059 3060 aResult += String(SW_RES(STR_REDLINE_INSERT + GetType())); 3061 3062 return aResult; 3063 } 3064 3065 /* */ 3066 3067 SwRedline::SwRedline(RedlineType_t eTyp, const SwPaM& rPam ) 3068 : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ), 3069 pRedlineData( new SwRedlineData( eTyp, GetDoc()->GetRedlineAuthor() ) ), 3070 pCntntSect( 0 ) 3071 { 3072 bDelLastPara = bIsLastParaDelete = sal_False; 3073 bIsVisible = sal_True; 3074 if( !rPam.HasMark() ) 3075 DeleteMark(); 3076 } 3077 3078 SwRedline::SwRedline( const SwRedlineData& rData, const SwPaM& rPam ) 3079 : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ), 3080 pRedlineData( new SwRedlineData( rData )), 3081 pCntntSect( 0 ) 3082 { 3083 bDelLastPara = bIsLastParaDelete = sal_False; 3084 bIsVisible = sal_True; 3085 if( !rPam.HasMark() ) 3086 DeleteMark(); 3087 } 3088 3089 SwRedline::SwRedline( const SwRedlineData& rData, const SwPosition& rPos ) 3090 : SwPaM( rPos ), 3091 pRedlineData( new SwRedlineData( rData )), 3092 pCntntSect( 0 ) 3093 { 3094 bDelLastPara = bIsLastParaDelete = sal_False; 3095 bIsVisible = sal_True; 3096 } 3097 3098 SwRedline::SwRedline( const SwRedline& rCpy ) 3099 : SwPaM( *rCpy.GetMark(), *rCpy.GetPoint() ), 3100 pRedlineData( new SwRedlineData( *rCpy.pRedlineData )), 3101 pCntntSect( 0 ) 3102 { 3103 bDelLastPara = bIsLastParaDelete = sal_False; 3104 bIsVisible = sal_True; 3105 if( !rCpy.HasMark() ) 3106 DeleteMark(); 3107 } 3108 3109 SwRedline::~SwRedline() 3110 { 3111 if( pCntntSect ) 3112 { 3113 // dann den Content Bereich loeschen 3114 if( !GetDoc()->IsInDtor() ) 3115 GetDoc()->DeleteSection( &pCntntSect->GetNode() ); 3116 delete pCntntSect; 3117 } 3118 delete pRedlineData; 3119 } 3120 3121 // liegt eine gueltige Selektion vor? 3122 sal_Bool SwRedline::HasValidRange() const 3123 { 3124 const SwNode* pPtNd = &GetPoint()->nNode.GetNode(), 3125 * pMkNd = &GetMark()->nNode.GetNode(); 3126 if( pPtNd->StartOfSectionNode() == pMkNd->StartOfSectionNode() && 3127 !pPtNd->StartOfSectionNode()->IsTableNode() && 3128 // JP 18.5.2001: Bug 87222 - invalid if points on the end of content 3129 // DVO 25.03.2002: #96530# end-of-content only invalid if no content 3130 // index exists 3131 ( pPtNd != pMkNd || GetContentIdx() != NULL || 3132 pPtNd != &pPtNd->GetNodes().GetEndOfContent() ) 3133 ) 3134 return sal_True; 3135 return sal_False; 3136 } 3137 3138 void SwRedline::CallDisplayFunc( sal_uInt16 nLoop ) 3139 { 3140 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() ) 3141 { 3142 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE: 3143 Show( nLoop ); 3144 break; 3145 case nsRedlineMode_t::REDLINE_SHOW_INSERT: 3146 Hide( nLoop ); 3147 break; 3148 case nsRedlineMode_t::REDLINE_SHOW_DELETE: 3149 ShowOriginal( nLoop ); 3150 break; 3151 } 3152 } 3153 3154 void SwRedline::Show( sal_uInt16 nLoop ) 3155 { 3156 if( 1 <= nLoop ) 3157 { 3158 SwDoc* pDoc = GetDoc(); 3159 RedlineMode_t eOld = pDoc->GetRedlineMode(); 3160 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE)); 3161 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 3162 3163 switch( GetType() ) 3164 { 3165 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt 3166 bIsVisible = sal_True; 3167 MoveFromSection(); 3168 break; 3169 3170 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht 3171 bIsVisible = sal_True; 3172 MoveFromSection(); 3173 break; 3174 3175 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet 3176 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert 3177 InvalidateRange(); 3178 break; 3179 default: 3180 break; 3181 } 3182 pDoc->SetRedlineMode_intern( eOld ); 3183 } 3184 } 3185 3186 void SwRedline::Hide( sal_uInt16 nLoop ) 3187 { 3188 SwDoc* pDoc = GetDoc(); 3189 RedlineMode_t eOld = pDoc->GetRedlineMode(); 3190 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE)); 3191 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 3192 3193 switch( GetType() ) 3194 { 3195 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt 3196 bIsVisible = sal_True; 3197 if( 1 <= nLoop ) 3198 MoveFromSection(); 3199 break; 3200 3201 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht 3202 bIsVisible = sal_False; 3203 switch( nLoop ) 3204 { 3205 case 0: MoveToSection(); break; 3206 case 1: CopyToSection(); break; 3207 case 2: DelCopyOfSection(); break; 3208 } 3209 break; 3210 3211 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet 3212 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert 3213 if( 1 <= nLoop ) 3214 InvalidateRange(); 3215 break; 3216 default: 3217 break; 3218 } 3219 pDoc->SetRedlineMode_intern( eOld ); 3220 } 3221 3222 void SwRedline::ShowOriginal( sal_uInt16 nLoop ) 3223 { 3224 SwDoc* pDoc = GetDoc(); 3225 RedlineMode_t eOld = pDoc->GetRedlineMode(); 3226 SwRedlineData* pCur; 3227 3228 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE)); 3229 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 3230 3231 // bestimme den Type, ist der erste auf Stack 3232 for( pCur = pRedlineData; pCur->pNext; ) 3233 pCur = pCur->pNext; 3234 3235 switch( pCur->eType ) 3236 { 3237 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt 3238 bIsVisible = sal_False; 3239 switch( nLoop ) 3240 { 3241 case 0: MoveToSection(); break; 3242 case 1: CopyToSection(); break; 3243 case 2: DelCopyOfSection(); break; 3244 } 3245 break; 3246 3247 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht 3248 bIsVisible = sal_True; 3249 if( 1 <= nLoop ) 3250 MoveFromSection(); 3251 break; 3252 3253 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet 3254 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert 3255 if( 1 <= nLoop ) 3256 InvalidateRange(); 3257 break; 3258 default: 3259 break; 3260 } 3261 pDoc->SetRedlineMode_intern( eOld ); 3262 } 3263 3264 3265 void SwRedline::InvalidateRange() // das Layout anstossen 3266 { 3267 sal_uLong nSttNd = GetMark()->nNode.GetIndex(), 3268 nEndNd = GetPoint()->nNode.GetIndex(); 3269 sal_uInt16 nSttCnt = GetMark()->nContent.GetIndex(), 3270 nEndCnt = GetPoint()->nContent.GetIndex(); 3271 3272 if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt )) 3273 { 3274 sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp; 3275 nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (sal_uInt16)nTmp; 3276 } 3277 3278 SwUpdateAttr aHt( 0, 0, RES_FMT_CHG ); 3279 SwNodes& rNds = GetDoc()->GetNodes(); 3280 SwNode* pNd; 3281 for( sal_uLong n = nSttNd; n <= nEndNd; ++n ) 3282 if( ND_TEXTNODE == ( pNd = rNds[ n ] )->GetNodeType() ) 3283 { 3284 aHt.nStart = n == nSttNd ? nSttCnt : 0; 3285 aHt.nEnd = n == nEndNd ? nEndCnt : ((SwTxtNode*)pNd)->GetTxt().Len(); 3286 ((SwTxtNode*)pNd)->ModifyNotification( &aHt, &aHt ); 3287 } 3288 } 3289 3290 /************************************************************************* 3291 * SwRedline::CalcStartEnd() 3292 * Calculates the start and end position of the intersection rTmp and 3293 * text node nNdIdx 3294 *************************************************************************/ 3295 3296 void SwRedline::CalcStartEnd( sal_uLong nNdIdx, sal_uInt16& nStart, sal_uInt16& nEnd ) const 3297 { 3298 const SwPosition *pRStt = Start(), *pREnd = End(); 3299 if( pRStt->nNode < nNdIdx ) 3300 { 3301 if( pREnd->nNode > nNdIdx ) 3302 { 3303 nStart = 0; // Absatz ist komplett enthalten 3304 nEnd = STRING_LEN; 3305 } 3306 else 3307 { 3308 ASSERT( pREnd->nNode == nNdIdx, 3309 "SwRedlineItr::Seek: GetRedlinePos Error" ); 3310 nStart = 0; // Absatz wird vorne ueberlappt 3311 nEnd = pREnd->nContent.GetIndex(); 3312 } 3313 } 3314 else if( pRStt->nNode == nNdIdx ) 3315 { 3316 nStart = pRStt->nContent.GetIndex(); 3317 if( pREnd->nNode == nNdIdx ) 3318 nEnd = pREnd->nContent.GetIndex(); // Innerhalb des Absatzes 3319 else 3320 nEnd = STRING_LEN; // Absatz wird hinten ueberlappt 3321 } 3322 else 3323 { 3324 nStart = STRING_LEN; 3325 nEnd = STRING_LEN; 3326 } 3327 } 3328 3329 void SwRedline::MoveToSection() 3330 { 3331 if( !pCntntSect ) 3332 { 3333 const SwPosition* pStt = Start(), 3334 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint(); 3335 3336 SwDoc* pDoc = GetDoc(); 3337 SwPaM aPam( *pStt, *pEnd ); 3338 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode(); 3339 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode(); 3340 3341 if( !pCSttNd ) 3342 { 3343 // damit die Indizies der anderen Redlines nicht mitverschoben 3344 // werden, diese aufs Ende setzen (ist exclusive). 3345 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 3346 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 3347 { 3348 SwRedline* pRedl = rTbl[ n ]; 3349 if( pRedl->GetBound(sal_True) == *pStt ) 3350 pRedl->GetBound(sal_True) = *pEnd; 3351 if( pRedl->GetBound(sal_False) == *pStt ) 3352 pRedl->GetBound(sal_False) = *pEnd; 3353 } 3354 } 3355 3356 SwStartNode* pSttNd; 3357 SwNodes& rNds = pDoc->GetNodes(); 3358 if( pCSttNd || pCEndNd ) 3359 { 3360 SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() ) 3361 ? ((SwTxtNode*)pCSttNd)->GetTxtColl() 3362 : (pCEndNd && pCEndNd->IsTxtNode() ) 3363 ? ((SwTxtNode*)pCEndNd)->GetTxtColl() 3364 : pDoc->GetTxtCollFromPool( 3365 RES_POOLCOLL_STANDARD ); 3366 3367 pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ), 3368 SwNormalStartNode, pColl ); 3369 SwTxtNode* pTxtNd = rNds[ pSttNd->GetIndex() + 1 ]->GetTxtNode(); 3370 3371 SwNodeIndex aNdIdx( *pTxtNd ); 3372 SwPosition aPos( aNdIdx, SwIndex( pTxtNd )); 3373 if( pCSttNd && pCEndNd ) 3374 pDoc->MoveAndJoin( aPam, aPos, IDocumentContentOperations::DOC_MOVEDEFAULT ); 3375 else 3376 { 3377 if( pCSttNd && !pCEndNd ) 3378 bDelLastPara = sal_True; 3379 pDoc->MoveRange( aPam, aPos, 3380 IDocumentContentOperations::DOC_MOVEDEFAULT ); 3381 } 3382 } 3383 else 3384 { 3385 pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ), 3386 SwNormalStartNode ); 3387 3388 SwPosition aPos( *pSttNd->EndOfSectionNode() ); 3389 pDoc->MoveRange( aPam, aPos, 3390 IDocumentContentOperations::DOC_MOVEDEFAULT ); 3391 } 3392 pCntntSect = new SwNodeIndex( *pSttNd ); 3393 3394 if( pStt == GetPoint() ) 3395 Exchange(); 3396 3397 DeleteMark(); 3398 } 3399 else 3400 InvalidateRange(); 3401 } 3402 3403 void SwRedline::CopyToSection() 3404 { 3405 if( !pCntntSect ) 3406 { 3407 const SwPosition* pStt = Start(), 3408 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint(); 3409 3410 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode(); 3411 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode(); 3412 3413 SwStartNode* pSttNd; 3414 SwDoc* pDoc = GetDoc(); 3415 SwNodes& rNds = pDoc->GetNodes(); 3416 3417 sal_Bool bSaveCopyFlag = pDoc->IsCopyIsMove(), 3418 bSaveRdlMoveFlg = pDoc->IsRedlineMove(); 3419 pDoc->SetCopyIsMove( sal_True ); 3420 3421 // #100619# The IsRedlineMove() flag causes the behaviour of the 3422 // SwDoc::_CopyFlyInFly method to change, which will eventually be 3423 // called by the pDoc->Copy line below (through SwDoc::_Copy, 3424 // SwDoc::CopyWithFlyInFly). This rather obscure bugfix was introduced 3425 // for #63198# and #64896#, and apparently never really worked. 3426 pDoc->SetRedlineMove( pStt->nContent == 0 ); 3427 3428 if( pCSttNd ) 3429 { 3430 SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() ) 3431 ? ((SwTxtNode*)pCSttNd)->GetTxtColl() 3432 : pDoc->GetTxtCollFromPool( 3433 RES_POOLCOLL_STANDARD ); 3434 3435 pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ), 3436 SwNormalStartNode, pColl ); 3437 3438 SwNodeIndex aNdIdx( *pSttNd, 1 ); 3439 SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode(); 3440 SwPosition aPos( aNdIdx, SwIndex( pTxtNd )); 3441 pDoc->CopyRange( *this, aPos, false ); 3442 3443 // JP 08.10.98: die Vorlage vom EndNode ggfs. mit uebernehmen 3444 // - ist im Doc::Copy nicht erwuenscht 3445 if( pCEndNd && pCEndNd != pCSttNd ) 3446 { 3447 SwCntntNode* pDestNd = aPos.nNode.GetNode().GetCntntNode(); 3448 if( pDestNd ) 3449 { 3450 if( pDestNd->IsTxtNode() && pCEndNd->IsTxtNode() ) 3451 ((SwTxtNode*)pCEndNd)->CopyCollFmt( 3452 *(SwTxtNode*)pDestNd ); 3453 else 3454 pDestNd->ChgFmtColl( pCEndNd->GetFmtColl() ); 3455 } 3456 } 3457 } 3458 else 3459 { 3460 pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ), 3461 SwNormalStartNode ); 3462 3463 if( pCEndNd ) 3464 { 3465 SwPosition aPos( *pSttNd->EndOfSectionNode() ); 3466 pDoc->CopyRange( *this, aPos, false ); 3467 } 3468 else 3469 { 3470 SwNodeIndex aInsPos( *pSttNd->EndOfSectionNode() ); 3471 SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 ); 3472 pDoc->CopyWithFlyInFly( aRg, 0, aInsPos ); 3473 } 3474 } 3475 pCntntSect = new SwNodeIndex( *pSttNd ); 3476 3477 pDoc->SetCopyIsMove( bSaveCopyFlag ); 3478 pDoc->SetRedlineMove( bSaveRdlMoveFlg ); 3479 } 3480 } 3481 3482 void SwRedline::DelCopyOfSection() 3483 { 3484 if( pCntntSect ) 3485 { 3486 const SwPosition* pStt = Start(), 3487 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint(); 3488 3489 SwDoc* pDoc = GetDoc(); 3490 SwPaM aPam( *pStt, *pEnd ); 3491 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode(); 3492 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode(); 3493 3494 if( !pCSttNd ) 3495 { 3496 // damit die Indizies der anderen Redlines nicht mitverschoben 3497 // werden, diese aufs Ende setzen (ist exclusive). 3498 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 3499 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 3500 { 3501 SwRedline* pRedl = rTbl[ n ]; 3502 if( pRedl->GetBound(sal_True) == *pStt ) 3503 pRedl->GetBound(sal_True) = *pEnd; 3504 if( pRedl->GetBound(sal_False) == *pStt ) 3505 pRedl->GetBound(sal_False) = *pEnd; 3506 } 3507 } 3508 3509 if( pCSttNd && pCEndNd ) 3510 { 3511 // --> OD 2009-08-20 #i100466# 3512 // force a <join next> on <delete and join> operation 3513 pDoc->DeleteAndJoin( aPam, true ); 3514 // <-- 3515 } 3516 else if( pCSttNd || pCEndNd ) 3517 { 3518 if( pCSttNd && !pCEndNd ) 3519 bDelLastPara = sal_True; 3520 pDoc->DeleteRange( aPam ); 3521 3522 if( bDelLastPara ) 3523 { 3524 // #100611# To prevent dangling references to the paragraph to 3525 // be deleted, redline that point into this paragraph should be 3526 // moved to the new end position. Since redlines in the redline 3527 // table are sorted and the pEnd position is an endnode (see 3528 // bDelLastPara condition above), only redlines before the 3529 // current ones can be affected. 3530 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 3531 sal_uInt16 n = rTbl.GetPos( this ); 3532 ASSERT( n != USHRT_MAX, "How strange. We don't exist!" ); 3533 for( sal_Bool bBreak = sal_False; !bBreak && n > 0; ) 3534 { 3535 --n; 3536 bBreak = sal_True; 3537 if( rTbl[ n ]->GetBound(sal_True) == *aPam.GetPoint() ) 3538 { 3539 rTbl[ n ]->GetBound(sal_True) = *pEnd; 3540 bBreak = sal_False; 3541 } 3542 if( rTbl[ n ]->GetBound(sal_False) == *aPam.GetPoint() ) 3543 { 3544 rTbl[ n ]->GetBound(sal_False) = *pEnd; 3545 bBreak = sal_False; 3546 } 3547 } 3548 3549 SwPosition aEnd( *pEnd ); 3550 *GetPoint() = *pEnd; 3551 *GetMark() = *pEnd; 3552 DeleteMark(); 3553 3554 aPam.GetBound( sal_True ).nContent.Assign( 0, 0 ); 3555 aPam.GetBound( sal_False ).nContent.Assign( 0, 0 ); 3556 aPam.DeleteMark(); 3557 pDoc->DelFullPara( aPam ); 3558 } 3559 } 3560 else 3561 { 3562 pDoc->DeleteRange( aPam ); 3563 } 3564 3565 if( pStt == GetPoint() ) 3566 Exchange(); 3567 3568 DeleteMark(); 3569 } 3570 } 3571 3572 void SwRedline::MoveFromSection() 3573 { 3574 if( pCntntSect ) 3575 { 3576 SwDoc* pDoc = GetDoc(); 3577 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 3578 SvPtrarr aBeforeArr( 16, 16 ), aBehindArr( 16, 16 ); 3579 sal_uInt16 nMyPos = rTbl.GetPos( this ); 3580 ASSERT( this, "this nicht im Array?" ); 3581 sal_Bool bBreak = sal_False; 3582 sal_uInt16 n; 3583 3584 for( n = nMyPos+1; !bBreak && n < rTbl.Count(); ++n ) 3585 { 3586 bBreak = sal_True; 3587 if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() ) 3588 { 3589 void* pTmp = &rTbl[ n ]->GetBound(sal_True); 3590 aBehindArr.Insert( pTmp, aBehindArr.Count()); 3591 bBreak = sal_False; 3592 } 3593 if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() ) 3594 { 3595 void* pTmp = &rTbl[ n ]->GetBound(sal_False); 3596 aBehindArr.Insert( pTmp, aBehindArr.Count() ); 3597 bBreak = sal_False; 3598 } 3599 } 3600 for( bBreak = sal_False, n = nMyPos; !bBreak && n ; ) 3601 { 3602 --n; 3603 bBreak = sal_True; 3604 if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() ) 3605 { 3606 void* pTmp = &rTbl[ n ]->GetBound(sal_True); 3607 aBeforeArr.Insert( pTmp, aBeforeArr.Count() ); 3608 bBreak = sal_False; 3609 } 3610 if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() ) 3611 { 3612 void* pTmp = &rTbl[ n ]->GetBound(sal_False); 3613 aBeforeArr.Insert( pTmp, aBeforeArr.Count() ); 3614 bBreak = sal_False; 3615 } 3616 } 3617 3618 // --> OD 2009-03-17 #i95711# 3619 const SwNode* pKeptCntntSectNode( &pCntntSect->GetNode() ); 3620 // <-- 3621 { 3622 SwPaM aPam( pCntntSect->GetNode(), 3623 *pCntntSect->GetNode().EndOfSectionNode(), 1, 3624 ( bDelLastPara ? -2 : -1 ) ); 3625 SwCntntNode* pCNd = aPam.GetCntntNode(); 3626 if( pCNd ) 3627 aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); 3628 else 3629 aPam.GetPoint()->nNode++; 3630 3631 SwFmtColl* pColl = pCNd && pCNd->Len() && aPam.GetPoint()->nNode != 3632 aPam.GetMark()->nNode 3633 ? pCNd->GetFmtColl() : 0; 3634 3635 SwNodeIndex aNdIdx( GetPoint()->nNode, -1 ); 3636 sal_uInt16 nPos = GetPoint()->nContent.GetIndex(); 3637 3638 SwPosition aPos( *GetPoint() ); 3639 if( bDelLastPara && *aPam.GetPoint() == *aPam.GetMark() ) 3640 { 3641 aPos.nNode--; 3642 3643 pDoc->AppendTxtNode( aPos ); 3644 } 3645 else 3646 { 3647 pDoc->MoveRange( aPam, aPos, 3648 IDocumentContentOperations::DOC_MOVEALLFLYS ); 3649 } 3650 3651 SetMark(); 3652 *GetPoint() = aPos; 3653 GetMark()->nNode = aNdIdx.GetIndex() + 1; 3654 pCNd = GetMark()->nNode.GetNode().GetCntntNode(); 3655 GetMark()->nContent.Assign( pCNd, nPos ); 3656 3657 if( bDelLastPara ) 3658 { 3659 GetPoint()->nNode++; 3660 GetPoint()->nContent.Assign( pCNd = GetCntntNode(), 0 ); 3661 bDelLastPara = sal_False; 3662 } 3663 else if( pColl ) 3664 pCNd = GetCntntNode(); 3665 3666 if( pColl && pCNd ) 3667 pCNd->ChgFmtColl( pColl ); 3668 } 3669 // --> OD 2009-03-17 #i95771# 3670 // Under certain conditions the previous <SwDoc::Move(..)> has already 3671 // remove the change tracking section of this <SwRedline> instance from 3672 // the change tracking nodes area. 3673 // Thus, check, if <pCntntSect> still points to the change tracking section 3674 // by comparing it with the "indexed" <SwNode> instance copied before 3675 // perform the intrinsic move. 3676 // Note: Such condition is e.g. a "delete" change tracking only containing a table. 3677 if ( &pCntntSect->GetNode() == pKeptCntntSectNode ) 3678 { 3679 pDoc->DeleteSection( &pCntntSect->GetNode() ); 3680 } 3681 // <-- 3682 delete pCntntSect, pCntntSect = 0; 3683 3684 // #100611# adjustment of redline table positions must take start and 3685 // end into account, not point and mark. 3686 for( n = 0; n < aBeforeArr.Count(); ++n ) 3687 *(SwPosition*)aBeforeArr[ n ] = *Start(); 3688 for( n = 0; n < aBehindArr.Count(); ++n ) 3689 *(SwPosition*)aBehindArr[ n ] = *End(); 3690 } 3691 else 3692 InvalidateRange(); 3693 } 3694 3695 // fuers Undo 3696 void SwRedline::SetContentIdx( const SwNodeIndex* pIdx ) 3697 { 3698 if( pIdx && !pCntntSect ) 3699 { 3700 pCntntSect = new SwNodeIndex( *pIdx ); 3701 bIsVisible = sal_False; 3702 } 3703 else if( !pIdx && pCntntSect ) 3704 { 3705 delete pCntntSect, pCntntSect = 0; 3706 bIsVisible = sal_False; 3707 } 3708 #ifdef DBG_UTIL 3709 else 3710 ASSERT( !this, "das ist keine gueltige Operation" ); 3711 #endif 3712 } 3713 3714 sal_Bool SwRedline::CanCombine( const SwRedline& rRedl ) const 3715 { 3716 return IsVisible() && rRedl.IsVisible() && 3717 pRedlineData->CanCombine( *rRedl.pRedlineData ); 3718 } 3719 3720 void SwRedline::PushData( const SwRedline& rRedl, sal_Bool bOwnAsNext ) 3721 { 3722 // SwRedlineData* pNew = new SwRedlineData( rRedl.GetType(), 3723 // rRedl.GetAuthor() ); 3724 SwRedlineData* pNew = new SwRedlineData( *rRedl.pRedlineData, sal_False ); 3725 if( bOwnAsNext ) 3726 { 3727 pNew->pNext = pRedlineData; 3728 pRedlineData = pNew; 3729 } 3730 else 3731 { 3732 pNew->pNext = pRedlineData->pNext; 3733 pRedlineData->pNext = pNew; 3734 } 3735 } 3736 3737 sal_Bool SwRedline::PopData() 3738 { 3739 if( !pRedlineData->pNext ) 3740 return sal_False; 3741 SwRedlineData* pCur = pRedlineData; 3742 pRedlineData = pCur->pNext; 3743 pCur->pNext = 0; 3744 delete pCur; 3745 return sal_True; 3746 } 3747 3748 sal_uInt16 SwRedline::GetStackCount() const 3749 { 3750 sal_uInt16 nRet = 1; 3751 for( SwRedlineData* pCur = pRedlineData; pCur->pNext; ++nRet ) 3752 pCur = pCur->pNext; 3753 return nRet; 3754 } 3755 3756 // -> #111827# 3757 sal_uInt16 SwRedline::GetAuthor( sal_uInt16 nPos ) const 3758 { 3759 return GetRedlineData(nPos).nAuthor; 3760 } 3761 3762 const String& SwRedline::GetAuthorString( sal_uInt16 nPos ) const 3763 { 3764 return SW_MOD()->GetRedlineAuthor(GetRedlineData(nPos).nAuthor); 3765 } 3766 3767 const DateTime& SwRedline::GetTimeStamp( sal_uInt16 nPos ) const 3768 { 3769 return GetRedlineData(nPos).aStamp; 3770 } 3771 3772 RedlineType_t SwRedline::GetRealType( sal_uInt16 nPos ) const 3773 { 3774 return GetRedlineData(nPos).eType; 3775 } 3776 3777 const String& SwRedline::GetComment( sal_uInt16 nPos ) const 3778 { 3779 return GetRedlineData(nPos).sComment; 3780 } 3781 // <- #111827# 3782 3783 int SwRedline::operator==( const SwRedline& rCmp ) const 3784 { 3785 return this == &rCmp; 3786 } 3787 3788 int SwRedline::operator<( const SwRedline& rCmp ) const 3789 { 3790 sal_Bool nResult = sal_False; 3791 3792 if (*Start() < *rCmp.Start()) 3793 nResult = sal_True; 3794 else if (*Start() == *rCmp.Start()) 3795 if (*End() < *rCmp.End()) 3796 nResult = sal_True; 3797 3798 return nResult; 3799 } 3800 3801 // -> #111827# 3802 const SwRedlineData & SwRedline::GetRedlineData(sal_uInt16 nPos) const 3803 { 3804 SwRedlineData * pCur = pRedlineData; 3805 3806 while (nPos > 0 && NULL != pCur->pNext) 3807 { 3808 pCur = pCur->pNext; 3809 3810 nPos--; 3811 } 3812 3813 ASSERT( 0 == nPos, "Pos angabe ist zu gross" ); 3814 3815 return *pCur; 3816 } 3817 3818 String SwRedline::GetDescr(sal_uInt16 nPos) 3819 { 3820 String aResult; 3821 3822 // get description of redline data (e.g.: "insert $1") 3823 aResult = GetRedlineData(nPos).GetDescr(); 3824 3825 SwPaM * pPaM = NULL; 3826 bool bDeletePaM = false; 3827 3828 // if this redline is visible the content is in this PaM 3829 if (NULL == pCntntSect) 3830 { 3831 pPaM = this; 3832 } 3833 else // otherwise it is saved in pCntntSect 3834 { 3835 SwNodeIndex aTmpIdx( *pCntntSect->GetNode().EndOfSectionNode() ); 3836 pPaM = new SwPaM(*pCntntSect, aTmpIdx ); 3837 bDeletePaM = true; 3838 } 3839 3840 // replace $1 in description by description of the redlines text 3841 String aTmpStr; 3842 aTmpStr += String(SW_RES(STR_START_QUOTE)); 3843 aTmpStr += ShortenString(pPaM->GetTxt(), nUndoStringLength, 3844 String(SW_RES(STR_LDOTS))); 3845 aTmpStr += String(SW_RES(STR_END_QUOTE)); 3846 3847 SwRewriter aRewriter; 3848 aRewriter.AddRule(UNDO_ARG1, aTmpStr); 3849 3850 aResult = aRewriter.Apply(aResult); 3851 3852 if (bDeletePaM) 3853 delete pPaM; 3854 3855 return aResult; 3856 } 3857 // <- #111827# 3858 3859 3860 bool SwDoc::IsInRedlines(const SwNode & rNode) const 3861 { 3862 SwPosition aPos(rNode); 3863 SwNode & rEndOfRedlines = GetNodes().GetEndOfRedlines(); 3864 SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()), 3865 SwPosition(rEndOfRedlines)); 3866 3867 return aPam.ContainsPosition(aPos) ? true : false; 3868 } 3869