1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 28 #include <hintids.hxx> 29 #include <tools/shl.hxx> 30 #include <svl/itemiter.hxx> 31 #include <sfx2/app.hxx> 32 #include <editeng/colritem.hxx> 33 #include <editeng/udlnitem.hxx> 34 #include <editeng/crsditem.hxx> 35 #include <swmodule.hxx> 36 #include <doc.hxx> 37 #include <IDocumentUndoRedo.hxx> 38 #include <docary.hxx> 39 #include <ndtxt.hxx> 40 #include <redline.hxx> 41 #include <swundo.hxx> 42 #include <UndoCore.hxx> 43 #include <UndoRedline.hxx> 44 #include <hints.hxx> 45 #include <pamtyp.hxx> 46 #include <poolfmt.hxx> 47 #include <viewsh.hxx> 48 #include <rootfrm.hxx> 49 50 #include <comcore.hrc> 51 52 using namespace com::sun::star; 53 54 TYPEINIT1(SwRedlineHint, SfxHint); 55 56 #ifndef DBG_UTIL 57 58 #define _CHECK_REDLINE( pDoc ) 59 #define _DEBUG_REDLINE( pDoc ) 60 61 #else 62 63 #define _ERROR_PREFIX "redline table corrupted: " 64 65 // helper function for lcl_CheckRedline 66 // 1. make sure that pPos->nContent points into pPos->nNode 67 // (or into the 'special' no-content-node-IndexReg) 68 // 2. check that position is valid and doesn't point behind text 69 void lcl_CheckPosition( const SwPosition* pPos ) 70 { 71 SwPosition aComparePos( *pPos ); 72 aComparePos.nContent.Assign( 73 aComparePos.nNode.GetNode().GetCntntNode(), 0 ); 74 DBG_ASSERT( pPos->nContent.GetIdxReg() == 75 aComparePos.nContent.GetIdxReg(), 76 _ERROR_PREFIX "illegal position" ); 77 78 SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode(); 79 if( pTxtNode == NULL ) 80 { 81 DBG_ASSERT( pPos->nContent == 0, 82 _ERROR_PREFIX "non-text-node with content" ); 83 } 84 else 85 { 86 DBG_ASSERT( pPos->nContent >= 0 && 87 pPos->nContent <= pTxtNode->Len(), 88 _ERROR_PREFIX "index behind text" ); 89 } 90 } 91 92 void lcl_CheckPam( const SwPaM* pPam ) 93 { 94 DBG_ASSERT( pPam != NULL, _ERROR_PREFIX "illegal argument" ); 95 lcl_CheckPosition( pPam->GetPoint() ); 96 lcl_CheckPosition( pPam->GetMark() ); 97 } 98 99 // check validity of the redline table. Checks redline bounds, and make 100 // sure the redlines are sorted and non-overlapping. 101 void lcl_CheckRedline( const SwDoc* pDoc ) 102 { 103 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 104 105 // verify valid redline positions 106 for( sal_uInt16 i = 0; i < rTbl.Count(); ++i ) 107 lcl_CheckPam( rTbl[ i ] ); 108 109 for( sal_uInt16 j = 0; j < rTbl.Count(); ++j ) 110 { 111 // check for empty redlines 112 DBG_ASSERT( ( *(rTbl[j]->GetPoint()) != *(rTbl[j]->GetMark()) ) || 113 ( rTbl[j]->GetContentIdx() != NULL ), 114 _ERROR_PREFIX "empty redline" ); 115 } 116 117 // verify proper redline sorting 118 for( sal_uInt16 n = 1; n < rTbl.Count(); ++n ) 119 { 120 const SwRedline* pPrev = rTbl[ n-1 ]; 121 const SwRedline* pCurrent = rTbl[ n ]; 122 123 // check redline sorting 124 DBG_ASSERT( *pPrev->Start() <= *pCurrent->Start(), 125 _ERROR_PREFIX "not sorted correctly" ); 126 127 // check for overlapping redlines 128 DBG_ASSERT( *pPrev->End() <= *pCurrent->Start(), 129 _ERROR_PREFIX "overlapping redlines" ); 130 } 131 } 132 133 #define _CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc ); 134 135 void lcl_DebugRedline( const SwDoc* pDoc ) 136 { 137 static sal_uInt16 nWatch = 0; 138 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 139 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 140 { 141 sal_uInt16 nDummy = 0; 142 const SwRedline* pCurrent = rTbl[ n ]; 143 const SwRedline* pNext = n+1 < rTbl.Count() ? rTbl[ n+1 ] : 0; 144 if( pCurrent == pNext ) 145 ++nDummy; 146 if( n == nWatch ) 147 ++nDummy; // Possible debugger breakpoint 148 } 149 } 150 151 #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc ); 152 153 #endif 154 155 SV_IMPL_OP_PTRARR_SORT( _SwRedlineTbl, SwRedlinePtr ) 156 157 RedlineMode_t SwDoc::GetRedlineMode() const 158 { 159 return eRedlineMode; 160 } 161 162 void SwDoc::SetRedlineMode( RedlineMode_t eMode ) 163 { 164 if( eRedlineMode != eMode ) 165 { 166 if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) 167 || 0 == (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) ) 168 { 169 bool bSaveInXMLImportFlag = IsInXMLImport(); 170 SetInXMLImport( false ); 171 // und dann alles verstecken, anzeigen 172 void (SwRedline::*pFnc)( sal_uInt16 ) = 0; 173 174 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode ) 175 { 176 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE : 177 pFnc = &SwRedline::Show; 178 break; 179 case nsRedlineMode_t::REDLINE_SHOW_INSERT: 180 pFnc = &SwRedline::Hide; 181 break; 182 case nsRedlineMode_t::REDLINE_SHOW_DELETE: 183 pFnc = &SwRedline::ShowOriginal; 184 break; 185 186 default: 187 pFnc = &SwRedline::Hide; 188 eMode = (RedlineMode_t)(eMode | nsRedlineMode_t::REDLINE_SHOW_INSERT); 189 break; 190 } 191 192 _CHECK_REDLINE( this ) 193 194 if( pFnc ) 195 for( sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop ) 196 for( sal_uInt16 i = 0; i < pRedlineTbl->Count(); ++i ) 197 ((*pRedlineTbl)[ i ]->*pFnc)( nLoop ); 198 _CHECK_REDLINE( this ) 199 SetInXMLImport( bSaveInXMLImportFlag ); 200 } 201 eRedlineMode = eMode; 202 SetModified(); 203 } 204 } 205 206 bool SwDoc::IsRedlineOn() const 207 { 208 return IDocumentRedlineAccess::IsRedlineOn(eRedlineMode); 209 } 210 211 bool SwDoc::IsIgnoreRedline() const 212 { 213 return (nsRedlineMode_t::REDLINE_IGNORE & eRedlineMode); 214 } 215 216 void SwDoc::SetRedlineMode_intern(RedlineMode_t eMode) 217 { 218 eRedlineMode = eMode; 219 } 220 221 const SwRedlineTbl& SwDoc::GetRedlineTbl() const 222 { 223 return *pRedlineTbl; 224 } 225 226 bool SwDoc::IsRedlineMove() const 227 { 228 return mbIsRedlineMove; 229 } 230 231 void SwDoc::SetRedlineMove(bool bFlag) 232 { 233 mbIsRedlineMove = bFlag; 234 } 235 236 const uno::Sequence <sal_Int8>& SwDoc::GetRedlinePassword() const 237 { 238 return aRedlinePasswd; 239 } 240 241 inline bool IsPrevPos( const SwPosition rPos1, const SwPosition rPos2 ) 242 { 243 const SwCntntNode* pCNd; 244 return 0 == rPos2.nContent.GetIndex() && 245 rPos2.nNode.GetIndex() - 1 == rPos1.nNode.GetIndex() && 246 0 != ( pCNd = rPos1.nNode.GetNode().GetCntntNode() ) 247 ? rPos1.nContent.GetIndex() == pCNd->Len() 248 : false; 249 } 250 251 #ifdef DEBUG 252 bool CheckPosition( const SwPosition* pStt, const SwPosition* pEnd ) 253 { 254 int nError = 0; 255 SwNode* pSttNode = &pStt->nNode.GetNode(); 256 SwNode* pEndNode = &pEnd->nNode.GetNode(); 257 SwNode* pSttTab = pSttNode->StartOfSectionNode()->FindTableNode(); 258 SwNode* pEndTab = pEndNode->StartOfSectionNode()->FindTableNode(); 259 SwNode* pSttStart = pSttNode; 260 while( pSttStart && (!pSttStart->IsStartNode() || pSttStart->IsSectionNode() || 261 pSttStart->IsTableNode() ) ) 262 pSttStart = pSttStart->StartOfSectionNode(); 263 SwNode* pEndStart = pEndNode; 264 while( pEndStart && (!pEndStart->IsStartNode() || pEndStart->IsSectionNode() || 265 pEndStart->IsTableNode() ) ) 266 pEndStart = pEndStart->StartOfSectionNode(); 267 if( pSttTab != pEndTab ) 268 nError = 1; 269 if( !pSttTab && pSttStart != pEndStart ) 270 nError |= 2; 271 if( nError ) 272 nError += 10; 273 return nError != 0; 274 } 275 #endif 276 277 /* 278 279 Text heisst, nicht von Redline "verseuchter" Text. 280 281 Verhalten von Insert-Redline: 282 - im Text - Redline Object einfuegen 283 - im InsertRedline (eigenes) - ignorieren, bestehendes wird 284 aufgespannt 285 - im InsertRedline (andere) - Insert Redline aufsplitten 286 Redline Object einfuegen 287 - in DeleteRedline - Delete Redline aufsplitten oder 288 am Ende/Anfang verschieben 289 290 Verhalten von Delete-Redline: 291 - im Text - Redline Object einfuegen 292 - im DeleteRedline (eigenes/andere) - ignorieren 293 - im InsertRedline (eigenes) - ignorieren, Zeichen aber loeschen 294 - im InsertRedline (andere) - Insert Redline aufsplitten 295 Redline Object einfuegen 296 - Ueberlappung von Text und - Text in eigenen Insert loeschen, 297 eigenem Insert im andereren Text aufspannen (bis 298 zum Insert! 299 - Ueberlappung von Text und - Redline Object einfuegen, der 300 anderem Insert andere Insert wird vom Delete 301 ueberlappt 302 */ 303 304 bool SwDoc::AppendRedline( SwRedline* pNewRedl, bool bCallDelete ) 305 { 306 #if 0 307 // #i93179# disabled: ASSERT in ~SwIndexReg #ifdef DBG_UTIL 308 SwRedline aCopy( *pNewRedl ); 309 #endif 310 bool bError = true; 311 _CHECK_REDLINE( this ) 312 313 if( IsRedlineOn() && !IsShowOriginal( eRedlineMode ) && 314 pNewRedl->GetAuthorString().Len() ) 315 { 316 pNewRedl->InvalidateRange(); 317 318 if( mbIsAutoFmtRedline ) 319 { 320 pNewRedl->SetAutoFmtFlag(); 321 if( pAutoFmtRedlnComment && pAutoFmtRedlnComment->Len() ) 322 { 323 pNewRedl->SetComment( *pAutoFmtRedlnComment ); 324 pNewRedl->SetSeqNo( nAutoFmtRedlnCommentNo ); 325 } 326 } 327 328 SwPosition* pStt = pNewRedl->Start(), 329 * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark() 330 : pNewRedl->GetPoint(); 331 { 332 SwTxtNode* pTxtNode = pStt->nNode.GetNode().GetTxtNode(); 333 if( pTxtNode == NULL ) 334 { 335 if( pStt->nContent > 0 ) 336 { 337 DBG_ASSERT( false, "Redline start: non-text-node with content" ); 338 pStt->nContent = 0; 339 } 340 } 341 else 342 { 343 if( pStt->nContent > pTxtNode->Len() ) 344 { 345 DBG_ASSERT( false, "Redline start: index behind text" ); 346 pStt->nContent = pTxtNode->Len(); 347 } 348 } 349 pTxtNode = pEnd->nNode.GetNode().GetTxtNode(); 350 if( pTxtNode == NULL ) 351 { 352 if( pEnd->nContent > 0 ) 353 { 354 DBG_ASSERT( false, "Redline end: non-text-node with content" ); 355 pEnd->nContent = 0; 356 } 357 } 358 else 359 { 360 if( pEnd->nContent > pTxtNode->Len() ) 361 { 362 DBG_ASSERT( false, "Redline end: index behind text" ); 363 pEnd->nContent = pTxtNode->Len(); 364 } 365 } 366 } 367 if( ( *pStt == *pEnd ) && 368 ( pNewRedl->GetContentIdx() == NULL ) ) 369 { // Do not insert empty redlines 370 delete pNewRedl; 371 return sal_False; 372 } 373 sal_Bool bCompress = sal_False; 374 sal_uInt16 n = 0; 375 // zur StartPos das erste Redline suchen 376 if( !GetRedline( *pStt, &n ) && n ) 377 --n; 378 bool bDec = false; 379 380 for( ; pNewRedl && n < pRedlineTbl->Count(); bDec ? n : ++n ) 381 { 382 bDec = false; 383 #ifdef DVO_TEST 384 _CHECK_REDLINE( this ) 385 #endif 386 387 SwRedline* pRedl = (*pRedlineTbl)[ n ]; 388 SwPosition* pRStt = pRedl->Start(), 389 * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark() 390 : pRedl->GetPoint(); 391 392 // #i8518# remove empty redlines while we're at it 393 if( ( *pRStt == *pREnd ) && 394 ( pRedl->GetContentIdx() == NULL ) ) 395 { 396 pRedlineTbl->DeleteAndDestroy(n); 397 continue; 398 } 399 400 SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ); 401 402 switch( pNewRedl->GetType() ) 403 { 404 case nsRedlineType_t::REDLINE_INSERT: 405 switch( pRedl->GetType() ) 406 { 407 case nsRedlineType_t::REDLINE_INSERT: 408 if( pRedl->IsOwnRedline( *pNewRedl ) ) 409 { 410 bool bDelete = false; 411 412 // ggfs. verschmelzen? 413 if( (( POS_BEHIND == eCmpPos && 414 IsPrevPos( *pREnd, *pStt ) ) || 415 ( POS_COLLIDE_START == eCmpPos ) || 416 ( POS_OVERLAP_BEHIND == eCmpPos ) ) && 417 pRedl->CanCombine( *pNewRedl ) && 418 ( n+1 >= pRedlineTbl->Count() || 419 ( *(*pRedlineTbl)[ n+1 ]->Start() >= *pEnd && 420 *(*pRedlineTbl)[ n+1 ]->Start() != *pREnd ) ) ) 421 { 422 pRedl->SetEnd( *pEnd, pREnd ); 423 if( !pRedl->HasValidRange() ) 424 { 425 // neu einsortieren 426 pRedlineTbl->Remove( n ); 427 pRedlineTbl->Insert( pRedl ); 428 } 429 430 bError = false; 431 bDelete = true; 432 } 433 else if( (( POS_BEFORE == eCmpPos && 434 IsPrevPos( *pEnd, *pRStt ) ) || 435 ( POS_COLLIDE_END == eCmpPos ) || 436 ( POS_OVERLAP_BEFORE == eCmpPos ) ) && 437 pRedl->CanCombine( *pNewRedl ) && 438 ( !n || 439 *(*pRedlineTbl)[ n-1 ]->End() != *pRStt )) 440 { 441 pRedl->SetStart( *pStt, pRStt ); 442 // neu einsortieren 443 pRedlineTbl->Remove( n ); 444 pRedlineTbl->Insert( pRedl ); 445 446 bError = false; 447 bDelete = true; 448 } 449 else if ( POS_OUTSIDE == eCmpPos ) 450 { 451 // #107164# own insert-over-insert 452 // redlines: just scrap the inside ones 453 pRedlineTbl->Remove( n ); 454 bDec = true; 455 } 456 // <- #107164# 457 else if( POS_OVERLAP_BEHIND == eCmpPos ) 458 { 459 *pStt = *pREnd; 460 if( ( *pStt == *pEnd ) && 461 ( pNewRedl->GetContentIdx() == NULL ) ) 462 bDelete = true; 463 } 464 else if( POS_OVERLAP_BEFORE == eCmpPos ) 465 { 466 *pEnd = *pRStt; 467 if( ( *pStt == *pEnd ) && 468 ( pNewRedl->GetContentIdx() == NULL ) ) 469 bDelete = true; 470 } 471 else if( POS_INSIDE == eCmpPos || POS_EQUAL == eCmpPos) 472 bDelete = true; 473 474 if( bDelete ) 475 { 476 delete pNewRedl, pNewRedl = 0; 477 bCompress = sal_True; 478 } 479 } 480 else if( POS_INSIDE == eCmpPos ) 481 { 482 // aufsplitten 483 if( *pEnd != *pREnd ) 484 { 485 SwRedline* pCpy = new SwRedline( *pRedl ); 486 pCpy->SetStart( *pEnd ); 487 pRedlineTbl->Insert( pCpy ); 488 } 489 pRedl->SetEnd( *pStt, pREnd ); 490 if( ( *pStt == *pRStt ) && 491 ( pRedl->GetContentIdx() == NULL ) ) 492 { 493 pRedlineTbl->DeleteAndDestroy( n ); 494 bDec = true; 495 } 496 else if( !pRedl->HasValidRange() ) 497 { 498 // neu einsortieren 499 pRedlineTbl->Remove( n ); 500 pRedlineTbl->Insert( pRedl ); 501 } 502 } 503 else if ( POS_OUTSIDE == eCmpPos ) 504 { 505 // #102366# handle overlapping redlines in broken 506 // documents 507 508 // split up the new redline, since it covers the 509 // existing redline. Insert the first part, and 510 // progress with the remainder as usual 511 SwRedline* pSplit = new SwRedline( *pNewRedl ); 512 pSplit->SetEnd( *pRStt ); 513 pNewRedl->SetStart( *pREnd ); 514 pRedlineTbl->Insert( pSplit ); 515 if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL ) 516 { 517 delete pNewRedl; 518 pNewRedl = 0; 519 bCompress = true; 520 } 521 } 522 else if ( POS_OVERLAP_BEHIND == eCmpPos ) 523 { 524 // #107164# handle overlapping redlines in broken 525 // documents 526 pNewRedl->SetStart( *pREnd ); 527 } 528 else if ( POS_OVERLAP_BEFORE == eCmpPos ) 529 { 530 // #107164# handle overlapping redlines in broken 531 // documents 532 *pEnd = *pRStt; 533 if( ( *pStt == *pEnd ) && 534 ( pNewRedl->GetContentIdx() == NULL ) ) 535 { 536 delete pNewRedl; 537 pNewRedl = 0; 538 bCompress = true; 539 } 540 } 541 break; 542 case nsRedlineType_t::REDLINE_DELETE: 543 if( POS_INSIDE == eCmpPos ) 544 { 545 // aufsplitten 546 if( *pEnd != *pREnd ) 547 { 548 SwRedline* pCpy = new SwRedline( *pRedl ); 549 pCpy->SetStart( *pEnd ); 550 pRedlineTbl->Insert( pCpy ); 551 } 552 pRedl->SetEnd( *pStt, pREnd ); 553 if( ( *pStt == *pRStt ) && 554 ( pRedl->GetContentIdx() == NULL ) ) 555 { 556 pRedlineTbl->DeleteAndDestroy( n ); 557 bDec = true; 558 } 559 else if( !pRedl->HasValidRange() ) 560 { 561 // neu einsortieren 562 pRedlineTbl->Remove( n ); 563 pRedlineTbl->Insert( pRedl, n ); 564 } 565 } 566 else if ( POS_OUTSIDE == eCmpPos ) 567 { 568 // #102366# handle overlapping redlines in broken 569 // documents 570 571 // split up the new redline, since it covers the 572 // existing redline. Insert the first part, and 573 // progress with the remainder as usual 574 SwRedline* pSplit = new SwRedline( *pNewRedl ); 575 pSplit->SetEnd( *pRStt ); 576 pNewRedl->SetStart( *pREnd ); 577 pRedlineTbl->Insert( pSplit ); 578 if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL ) 579 { 580 delete pNewRedl; 581 pNewRedl = 0; 582 bCompress = true; 583 } 584 } 585 else if ( POS_EQUAL == eCmpPos ) 586 { 587 // #112895# handle identical redlines in broken 588 // documents - delete old (delete) redline 589 pRedlineTbl->DeleteAndDestroy( n ); 590 bDec = true; 591 } 592 else if ( POS_OVERLAP_BEHIND == eCmpPos ) 593 { // Another workaround for broken redlines (#107164#) 594 pNewRedl->SetStart( *pREnd ); 595 } 596 break; 597 case nsRedlineType_t::REDLINE_FORMAT: 598 switch( eCmpPos ) 599 { 600 case POS_OVERLAP_BEFORE: 601 pRedl->SetStart( *pEnd, pRStt ); 602 // neu einsortieren 603 pRedlineTbl->Remove( n ); 604 pRedlineTbl->Insert( pRedl, n ); 605 bDec = true; 606 break; 607 608 case POS_OVERLAP_BEHIND: 609 pRedl->SetEnd( *pStt, pREnd ); 610 if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL ) 611 { 612 pRedlineTbl->DeleteAndDestroy( n ); 613 bDec = true; 614 } 615 break; 616 617 case POS_EQUAL: 618 case POS_OUTSIDE: 619 // ueberlappt den akt. komplett oder hat gleiche 620 // Ausdehung, dann muss der alte geloescht werden 621 pRedlineTbl->DeleteAndDestroy( n ); 622 bDec = true; 623 break; 624 625 case POS_INSIDE: 626 // ueberlappt den akt. komplett, dann muss 627 // der neue gesplittet oder verkuertzt werden 628 if( *pEnd != *pREnd ) 629 { 630 if( *pEnd != *pRStt ) 631 { 632 SwRedline* pNew = new SwRedline( *pRedl ); 633 pNew->SetStart( *pEnd ); 634 pRedl->SetEnd( *pStt, pREnd ); 635 if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL ) 636 pRedlineTbl->DeleteAndDestroy( n ); 637 AppendRedline( pNew, bCallDelete ); 638 n = 0; // neu Aufsetzen 639 bDec = true; 640 } 641 } 642 else 643 pRedl->SetEnd( *pStt, pREnd ); 644 break; 645 default: 646 break; 647 } 648 break; 649 default: 650 break; 651 } 652 break; 653 654 case nsRedlineType_t::REDLINE_DELETE: 655 switch( pRedl->GetType() ) 656 { 657 case nsRedlineType_t::REDLINE_DELETE: 658 switch( eCmpPos ) 659 { 660 case POS_OUTSIDE: 661 { 662 // ueberlappt den akt. komplett 663 // dann muss der neue gesplittet werden 664 if( *pEnd != *pREnd ) 665 { 666 SwRedline* pNew = new SwRedline( *pNewRedl ); 667 pNew->SetStart( *pREnd ); 668 pNewRedl->SetEnd( *pRStt, pEnd ); 669 AppendRedline( pNew, bCallDelete ); 670 n = 0; // neu Aufsetzen 671 bDec = true; 672 } 673 else 674 pNewRedl->SetEnd( *pRStt, pEnd ); 675 } 676 break; 677 678 case POS_INSIDE: 679 case POS_EQUAL: 680 delete pNewRedl, pNewRedl = 0; 681 bCompress = sal_True; 682 break; 683 684 case POS_OVERLAP_BEFORE: 685 case POS_OVERLAP_BEHIND: 686 if( pRedl->IsOwnRedline( *pNewRedl ) && 687 // 1 == pRedl->GetStackCount() && 688 pRedl->CanCombine( *pNewRedl )) 689 { 690 // dann kann das zusammengefasst werden, sprich 691 // der neue deckt das schon ab. 692 if( POS_OVERLAP_BEHIND == eCmpPos ) 693 pNewRedl->SetStart( *pRStt, pStt ); 694 else 695 pNewRedl->SetEnd( *pREnd, pEnd ); 696 pRedlineTbl->DeleteAndDestroy( n ); 697 bDec = true; 698 } 699 else if( POS_OVERLAP_BEHIND == eCmpPos ) 700 pNewRedl->SetStart( *pREnd, pStt ); 701 else 702 pNewRedl->SetEnd( *pRStt, pEnd ); 703 break; 704 705 case POS_COLLIDE_START: 706 case POS_COLLIDE_END: 707 if( pRedl->IsOwnRedline( *pNewRedl ) && 708 // 1 == pRedl->GetStackCount() && 709 pRedl->CanCombine( *pNewRedl ) ) 710 { 711 if( IsHideChanges( eRedlineMode )) 712 { 713 // dann erstmal sichtbar machen, bevor 714 // die zusammengefasst werden koennen! 715 // Damit pNew auch beim Verschieben der 716 // Indizies behandelt wird, erstmal 717 // temporaer einfuegen 718 pRedlineTbl->SavePtrInArr( pNewRedl ); 719 pRedl->Show(); 720 pRedlineTbl->Remove( pRedlineTbl->GetPos(pNewRedl )); 721 pRStt = pRedl->Start(); 722 pREnd = pRedl->End(); 723 } 724 725 // dann kann das zusammengefasst werden, sprich 726 // der neue deckt das schon ab. 727 if( POS_COLLIDE_START == eCmpPos ) 728 pNewRedl->SetStart( *pRStt, pStt ); 729 else 730 pNewRedl->SetEnd( *pREnd, pEnd ); 731 732 // delete current (below), and restart process with 733 // previous 734 sal_uInt16 nToBeDeleted = n; 735 bDec = true; 736 737 // #107359# Do it again, Sam! 738 // If you can do it for them, you can do it for me. 739 if( *(pNewRedl->Start()) <= *pREnd ) 740 { 741 // Whoooah, we just extended the new 'redline' 742 // beyond previous redlines, so better start 743 // again. Of course this is not supposed to 744 // happen, and in an ideal world it doesn't, 745 // but unfortunately this code is buggy and 746 // totally rotten so it does happen and we 747 // better fix it. 748 n = 0; 749 bDec = true; 750 } 751 752 pRedlineTbl->DeleteAndDestroy( nToBeDeleted ); 753 } 754 break; 755 default: 756 break; 757 } 758 break; 759 760 case nsRedlineType_t::REDLINE_INSERT: 761 { 762 // b62341295: Do not throw away redlines 763 // even if they are not allowed to be combined 764 RedlineMode_t eOld = eRedlineMode; 765 if( !( eOld & nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) && 766 pRedl->IsOwnRedline( *pNewRedl ) ) 767 { 768 769 // auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig 770 // zusammen fasst! Der ShowMode muss erhalten bleiben! 771 eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)); 772 switch( eCmpPos ) 773 { 774 case POS_EQUAL: 775 bCompress = sal_True; 776 pRedlineTbl->DeleteAndDestroy( n ); 777 bDec = true; 778 // kein break! 779 780 case POS_INSIDE: 781 if( bCallDelete ) 782 { 783 eRedlineMode = (RedlineMode_t)(eRedlineMode | nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES); 784 785 // #98863# DeleteAndJoin does not yield the 786 // desired result if there is no paragraph to 787 // join with, i.e. at the end of the document. 788 // For this case, we completely delete the 789 // paragraphs (if, of course, we also start on 790 // a paragraph boundary). 791 if( (pStt->nContent == 0) && 792 pEnd->nNode.GetNode().IsEndNode() ) 793 { 794 pEnd->nNode--; 795 pEnd->nContent.Assign( 796 pEnd->nNode.GetNode().GetTxtNode(), 0); 797 DelFullPara( *pNewRedl ); 798 } 799 else 800 DeleteAndJoin( *pNewRedl ); 801 802 bCompress = sal_True; 803 } 804 delete pNewRedl, pNewRedl = 0; 805 break; 806 807 case POS_OUTSIDE: 808 { 809 pRedlineTbl->Remove( n ); 810 bDec = true; 811 // damit pNew auch beim Verschieben der Indizies 812 // behandelt wird, erstmal temp. einfuegen 813 if( bCallDelete ) 814 { 815 pRedlineTbl->SavePtrInArr( pNewRedl ); 816 DeleteAndJoin( *pRedl ); 817 sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl ); 818 if( USHRT_MAX != nFnd ) 819 pRedlineTbl->Remove( nFnd ); 820 else 821 pNewRedl = 0; 822 } 823 delete pRedl; 824 } 825 break; 826 827 case POS_OVERLAP_BEFORE: 828 { 829 SwPaM aPam( *pRStt, *pEnd ); 830 831 if( *pEnd == *pREnd ) 832 pRedlineTbl->DeleteAndDestroy( n ); 833 else 834 { 835 pRedl->SetStart( *pEnd, pRStt ); 836 // neu einsortieren 837 pRedlineTbl->Remove( n ); 838 pRedlineTbl->Insert( pRedl, n ); 839 } 840 841 if( bCallDelete ) 842 { 843 // damit pNew auch beim Verschieben der Indizies 844 // behandelt wird, erstmal temp. einfuegen 845 pRedlineTbl->SavePtrInArr( pNewRedl ); 846 DeleteAndJoin( aPam ); 847 sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl ); 848 if( USHRT_MAX != nFnd ) 849 pRedlineTbl->Remove( nFnd ); 850 else 851 pNewRedl = 0; 852 n = 0; // neu Aufsetzen 853 } 854 bDec = true; 855 } 856 break; 857 858 case POS_OVERLAP_BEHIND: 859 { 860 SwPaM aPam( *pStt, *pREnd ); 861 862 if( *pStt == *pRStt ) 863 { 864 pRedlineTbl->DeleteAndDestroy( n ); 865 bDec = true; 866 } 867 else 868 pRedl->SetEnd( *pStt, pREnd ); 869 870 if( bCallDelete ) 871 { 872 // damit pNew auch beim Verschieben der Indizies 873 // behandelt wird, erstmal temp. einfuegen 874 pRedlineTbl->SavePtrInArr( pNewRedl ); 875 DeleteAndJoin( aPam ); 876 sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl ); 877 if( USHRT_MAX != nFnd ) 878 pRedlineTbl->Remove( nFnd ); 879 else 880 pNewRedl = 0; 881 n = 0; // neu Aufsetzen 882 bDec = true; 883 } 884 } 885 break; 886 default: 887 break; 888 } 889 890 eRedlineMode = eOld; 891 } 892 else 893 { 894 // it may be necessary to split the existing redline in 895 // two. In this case, pRedl will be changed to cover 896 // only part of it's former range, and pNew will cover 897 // the remainder. 898 SwRedline* pNew = 0; 899 900 switch( eCmpPos ) 901 { 902 case POS_EQUAL: 903 { 904 pRedl->PushData( *pNewRedl ); 905 delete pNewRedl, pNewRedl = 0; 906 if( IsHideChanges( eRedlineMode )) 907 pRedl->Hide(); 908 bCompress = sal_True; 909 } 910 break; 911 912 case POS_INSIDE: 913 { 914 if( *pRStt == *pStt ) 915 { 916 // --> mst 2010-05-17 #i97421# 917 // redline w/out extent loops 918 if (*pStt != *pEnd) 919 // <-- 920 { 921 pNewRedl->PushData( *pRedl, sal_False ); 922 pRedl->SetStart( *pEnd, pRStt ); 923 // re-insert 924 pRedlineTbl->Remove( n ); 925 pRedlineTbl->Insert( pRedl, n ); 926 bDec = true; 927 } 928 } 929 else 930 { 931 pNewRedl->PushData( *pRedl, sal_False ); 932 if( *pREnd != *pEnd ) 933 { 934 pNew = new SwRedline( *pRedl ); 935 pNew->SetStart( *pEnd ); 936 } 937 pRedl->SetEnd( *pStt, pREnd ); 938 if( !pRedl->HasValidRange() ) 939 { 940 // neu einsortieren 941 pRedlineTbl->Remove( n ); 942 pRedlineTbl->Insert( pRedl, n ); 943 } 944 } 945 } 946 break; 947 948 case POS_OUTSIDE: 949 { 950 pRedl->PushData( *pNewRedl ); 951 if( *pEnd == *pREnd ) 952 pNewRedl->SetEnd( *pRStt, pEnd ); 953 else 954 { 955 pNew = new SwRedline( *pNewRedl ); 956 pNew->SetEnd( *pRStt ); 957 pNewRedl->SetStart( *pREnd, pStt ); 958 } 959 bCompress = sal_True; 960 } 961 break; 962 963 case POS_OVERLAP_BEFORE: 964 { 965 if( *pEnd == *pREnd ) 966 { 967 pRedl->PushData( *pNewRedl ); 968 pNewRedl->SetEnd( *pRStt, pEnd ); 969 if( IsHideChanges( eRedlineMode )) 970 { 971 pRedlineTbl->SavePtrInArr( pNewRedl ); 972 pRedl->Hide(); 973 pRedlineTbl->Remove( 974 pRedlineTbl->GetPos(pNewRedl )); 975 } 976 } 977 else 978 { 979 pNew = new SwRedline( *pRedl ); 980 pNew->PushData( *pNewRedl ); 981 pNew->SetEnd( *pEnd ); 982 pNewRedl->SetEnd( *pRStt, pEnd ); 983 pRedl->SetStart( *pNew->End(), pRStt ) ; 984 // neu einsortieren 985 pRedlineTbl->Remove( n ); 986 pRedlineTbl->Insert( pRedl ); 987 bDec = true; 988 } 989 } 990 break; 991 992 case POS_OVERLAP_BEHIND: 993 { 994 if( *pStt == *pRStt ) 995 { 996 pRedl->PushData( *pNewRedl ); 997 pNewRedl->SetStart( *pREnd, pStt ); 998 if( IsHideChanges( eRedlineMode )) 999 { 1000 pRedlineTbl->SavePtrInArr( pNewRedl ); 1001 pRedl->Hide(); 1002 pRedlineTbl->Remove( 1003 pRedlineTbl->GetPos(pNewRedl )); 1004 } 1005 } 1006 else 1007 { 1008 pNew = new SwRedline( *pRedl ); 1009 pNew->PushData( *pNewRedl ); 1010 pNew->SetStart( *pStt ); 1011 pNewRedl->SetStart( *pREnd, pStt ); 1012 pRedl->SetEnd( *pNew->Start(), pREnd ); 1013 if( !pRedl->HasValidRange() ) 1014 { 1015 // neu einsortieren 1016 pRedlineTbl->Remove( n ); 1017 pRedlineTbl->Insert( pRedl ); 1018 } 1019 } 1020 } 1021 break; 1022 default: 1023 break; 1024 } 1025 1026 // insert the pNew part (if it exists) 1027 if( pNew ) 1028 { 1029 // AppendRedline( pNew, bCallDelete ); 1030 //sal_Bool bRet = 1031 pRedlineTbl->Insert( pNew ); 1032 1033 // pNew must be deleted if Insert() wasn't 1034 // successful. But that can't happen, since pNew is 1035 // part of the original pRedl redline. 1036 // ASSERT( bRet, "Can't insert existing redline?" ); 1037 1038 // restart (now with pRedl being split up) 1039 n = 0; 1040 bDec = true; 1041 } 1042 } 1043 } 1044 break; 1045 1046 case nsRedlineType_t::REDLINE_FORMAT: 1047 switch( eCmpPos ) 1048 { 1049 case POS_OVERLAP_BEFORE: 1050 pRedl->SetStart( *pEnd, pRStt ); 1051 // neu einsortieren 1052 pRedlineTbl->Remove( n ); 1053 pRedlineTbl->Insert( pRedl, n ); 1054 bDec = true; 1055 break; 1056 1057 case POS_OVERLAP_BEHIND: 1058 pRedl->SetEnd( *pStt, pREnd ); 1059 break; 1060 1061 case POS_EQUAL: 1062 case POS_OUTSIDE: 1063 // ueberlappt den akt. komplett oder hat gleiche 1064 // Ausdehung, dann muss der alte geloescht werden 1065 pRedlineTbl->DeleteAndDestroy( n ); 1066 bDec = true; 1067 break; 1068 1069 case POS_INSIDE: 1070 // ueberlappt den akt. komplett, dann muss 1071 // der neue gesplittet oder verkuertzt werden 1072 if( *pEnd != *pREnd ) 1073 { 1074 if( *pEnd != *pRStt ) 1075 { 1076 SwRedline* pNew = new SwRedline( *pRedl ); 1077 pNew->SetStart( *pEnd ); 1078 pRedl->SetEnd( *pStt, pREnd ); 1079 if( ( *pStt == *pRStt ) && 1080 ( pRedl->GetContentIdx() == NULL ) ) 1081 pRedlineTbl->DeleteAndDestroy( n ); 1082 AppendRedline( pNew, bCallDelete ); 1083 n = 0; // neu Aufsetzen 1084 bDec = true; 1085 } 1086 } 1087 else 1088 pRedl->SetEnd( *pStt, pREnd ); 1089 break; 1090 default: 1091 break; 1092 } 1093 break; 1094 default: 1095 break; 1096 } 1097 break; 1098 1099 case nsRedlineType_t::REDLINE_FORMAT: 1100 switch( pRedl->GetType() ) 1101 { 1102 case nsRedlineType_t::REDLINE_INSERT: 1103 case nsRedlineType_t::REDLINE_DELETE: 1104 switch( eCmpPos ) 1105 { 1106 case POS_OVERLAP_BEFORE: 1107 pNewRedl->SetEnd( *pRStt, pEnd ); 1108 break; 1109 1110 case POS_OVERLAP_BEHIND: 1111 pNewRedl->SetStart( *pREnd, pStt ); 1112 break; 1113 1114 case POS_EQUAL: 1115 case POS_INSIDE: 1116 delete pNewRedl, pNewRedl = 0; 1117 break; 1118 1119 case POS_OUTSIDE: 1120 // ueberlappt den akt. komplett, dann muss 1121 // der neue gesplittet oder verkuerzt werden 1122 if( *pEnd != *pREnd ) 1123 { 1124 if( *pEnd != *pRStt ) 1125 { 1126 SwRedline* pNew = new SwRedline( *pNewRedl ); 1127 pNew->SetStart( *pREnd ); 1128 pNewRedl->SetEnd( *pRStt, pEnd ); 1129 AppendRedline( pNew, bCallDelete ); 1130 n = 0; // neu Aufsetzen 1131 bDec = true; 1132 } 1133 } 1134 else 1135 pNewRedl->SetEnd( *pRStt, pEnd ); 1136 break; 1137 default: 1138 break; 1139 } 1140 break; 1141 case nsRedlineType_t::REDLINE_FORMAT: 1142 switch( eCmpPos ) 1143 { 1144 case POS_OUTSIDE: 1145 case POS_EQUAL: 1146 { 1147 // ueberlappt den akt. komplett oder hat gleiche 1148 // Ausdehnung, dann muss der alte geloescht werden 1149 pRedlineTbl->DeleteAndDestroy( n ); 1150 bDec = true; 1151 } 1152 break; 1153 1154 case POS_INSIDE: 1155 if( pRedl->IsOwnRedline( *pNewRedl ) && 1156 pRedl->CanCombine( *pNewRedl )) 1157 // ein eigenes kann komplett ignoriert werden 1158 delete pNewRedl, pNewRedl = 0; 1159 1160 else if( *pREnd == *pEnd ) 1161 // ansonsten nur den akt. verkuerzen 1162 pRedl->SetEnd( *pStt, pREnd ); 1163 else if( *pRStt == *pStt ) 1164 { 1165 // ansonsten nur den akt. verkuerzen 1166 pRedl->SetStart( *pEnd, pRStt ); 1167 // neu einsortieren 1168 pRedlineTbl->Remove( n ); 1169 pRedlineTbl->Insert( pRedl, n ); 1170 bDec = true; 1171 } 1172 else 1173 { 1174 // liegt komplett im akt. 1175 // dann muss der gesplittet werden 1176 SwRedline* pNew = new SwRedline( *pRedl ); 1177 pNew->SetStart( *pEnd ); 1178 pRedl->SetEnd( *pStt, pREnd ); 1179 AppendRedline( pNew, bCallDelete ); 1180 n = 0; // neu Aufsetzen 1181 bDec = true; 1182 } 1183 break; 1184 1185 case POS_OVERLAP_BEFORE: 1186 case POS_OVERLAP_BEHIND: 1187 if( pRedl->IsOwnRedline( *pNewRedl ) && 1188 pRedl->CanCombine( *pNewRedl )) 1189 { 1190 // dann kann das zusammengefasst werden, sprich 1191 // der neue deckt das schon ab. 1192 if( POS_OVERLAP_BEHIND == eCmpPos ) 1193 pNewRedl->SetStart( *pRStt, pStt ); 1194 else 1195 pNewRedl->SetEnd( *pREnd, pEnd ); 1196 pRedlineTbl->DeleteAndDestroy( n ); 1197 bDec = 0; 1198 } 1199 else if( POS_OVERLAP_BEHIND == eCmpPos ) 1200 pNewRedl->SetStart( *pREnd, pStt ); 1201 else 1202 pNewRedl->SetEnd( *pRStt, pEnd ); 1203 break; 1204 1205 case POS_COLLIDE_END: 1206 if( pRedl->IsOwnRedline( *pNewRedl ) && 1207 pRedl->CanCombine( *pNewRedl ) && n && 1208 *(*pRedlineTbl)[ n-1 ]->End() < *pStt ) 1209 { 1210 // dann kann das zusammengefasst werden, sprich 1211 // der neue deckt das schon ab. 1212 pNewRedl->SetEnd( *pREnd, pEnd ); 1213 pRedlineTbl->DeleteAndDestroy( n ); 1214 bDec = true; 1215 } 1216 break; 1217 case POS_COLLIDE_START: 1218 if( pRedl->IsOwnRedline( *pNewRedl ) && 1219 pRedl->CanCombine( *pNewRedl ) && 1220 n+1 < pRedlineTbl->Count() && 1221 *(*pRedlineTbl)[ n+1 ]->Start() < *pEnd ) 1222 { 1223 // dann kann das zusammengefasst werden, sprich 1224 // der neue deckt das schon ab. 1225 pNewRedl->SetStart( *pRStt, pStt ); 1226 pRedlineTbl->DeleteAndDestroy( n ); 1227 bDec = true; 1228 } 1229 break; 1230 default: 1231 break; 1232 } 1233 break; 1234 default: 1235 break; 1236 } 1237 break; 1238 1239 1240 case nsRedlineType_t::REDLINE_FMTCOLL: 1241 // wie soll das verhalten sein???? 1242 // erstmal so einfuegen 1243 break; 1244 default: 1245 break; 1246 } 1247 } 1248 1249 if( pNewRedl ) 1250 { 1251 if( ( *pStt == *pEnd ) && 1252 ( pNewRedl->GetContentIdx() == NULL ) ) 1253 { // Do not insert empty redlines 1254 delete pNewRedl; 1255 pNewRedl = 0; 1256 } 1257 else 1258 pRedlineTbl->Insert( pNewRedl ); 1259 } 1260 1261 if( bCompress ) 1262 CompressRedlines(); 1263 } 1264 else 1265 { 1266 if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() ) 1267 { 1268 RedlineMode_t eOld = eRedlineMode; 1269 // auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig 1270 // zusammen fasst! Der ShowMode muss erhalten bleiben! 1271 eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)); 1272 DeleteAndJoin( *pNewRedl ); 1273 eRedlineMode = eOld; 1274 } 1275 delete pNewRedl, pNewRedl = 0; 1276 } 1277 _CHECK_REDLINE( this ) 1278 1279 return ( 0 != pNewRedl ) || !bError; 1280 } 1281 1282 void SwDoc::CompressRedlines() 1283 { 1284 _CHECK_REDLINE( this ) 1285 1286 void (SwRedline::*pFnc)(sal_uInt16) = 0; 1287 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode ) 1288 { 1289 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE: 1290 pFnc = &SwRedline::Show; 1291 break; 1292 case nsRedlineMode_t::REDLINE_SHOW_INSERT: 1293 pFnc = &SwRedline::Hide; 1294 break; 1295 } 1296 1297 // versuche gleiche zusammenzufassen 1298 for( sal_uInt16 n = 1; n < pRedlineTbl->Count(); ++n ) 1299 { 1300 SwRedline* pPrev = (*pRedlineTbl)[ n-1 ], 1301 * pCur = (*pRedlineTbl)[ n ]; 1302 const SwPosition* pPrevStt = pPrev->Start(), 1303 * pPrevEnd = pPrevStt == pPrev->GetPoint() 1304 ? pPrev->GetMark() : pPrev->GetPoint(); 1305 const SwPosition* pCurStt = pCur->Start(), 1306 * pCurEnd = pCurStt == pCur->GetPoint() 1307 ? pCur->GetMark() : pCur->GetPoint(); 1308 if( *pPrevEnd == *pCurStt && pPrev->CanCombine( *pCur ) && 1309 pPrevStt->nNode.GetNode().StartOfSectionNode() == 1310 pCurEnd->nNode.GetNode().StartOfSectionNode() && 1311 !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() ) 1312 { 1313 // dann koennen die zusammen gefasst werden 1314 pPrev->Show(); 1315 pCur->Show(); 1316 1317 pPrev->SetEnd( *pCur->End() ); 1318 pRedlineTbl->DeleteAndDestroy( n ); 1319 --n; 1320 if( pFnc ) 1321 (pPrev->*pFnc)(0); 1322 } 1323 } 1324 _CHECK_REDLINE( this ) 1325 } 1326 1327 bool SwDoc::SplitRedline( const SwPaM& rRange ) 1328 { 1329 sal_Bool bChg = sal_False; 1330 sal_uInt16 n = 0; 1331 const SwPosition* pStt = rRange.Start(), 1332 * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark() 1333 : rRange.GetPoint(); 1334 GetRedline( *pStt, &n ); 1335 for( ; n < pRedlineTbl->Count() ; ++n ) 1336 { 1337 SwRedline* pTmp = (*pRedlineTbl)[ n ]; 1338 SwPosition* pTStt = pTmp->Start(), 1339 * pTEnd = pTStt == pTmp->GetPoint() ? pTmp->GetMark() 1340 : pTmp->GetPoint(); 1341 if( *pTStt <= *pStt && *pStt <= *pTEnd && 1342 *pTStt <= *pEnd && *pEnd <= *pTEnd ) 1343 { 1344 bChg = sal_True; 1345 int nn = 0; 1346 if( *pStt == *pTStt ) 1347 nn += 1; 1348 if( *pEnd == *pTEnd ) 1349 nn += 2; 1350 1351 SwRedline* pNew = 0; 1352 switch( nn ) 1353 { 1354 case 0: 1355 pNew = new SwRedline( *pTmp ); 1356 pTmp->SetEnd( *pStt, pTEnd ); 1357 pNew->SetStart( *pEnd ); 1358 break; 1359 1360 case 1: 1361 *pTStt = *pEnd; 1362 break; 1363 1364 case 2: 1365 *pTEnd = *pStt; 1366 break; 1367 1368 case 3: 1369 pTmp->InvalidateRange(); 1370 pRedlineTbl->DeleteAndDestroy( n-- ); 1371 pTmp = 0; 1372 break; 1373 } 1374 if( pTmp && !pTmp->HasValidRange() ) 1375 { 1376 // neu einsortieren 1377 pRedlineTbl->Remove( n ); 1378 pRedlineTbl->Insert( pTmp, n ); 1379 } 1380 if( pNew ) 1381 pRedlineTbl->Insert( pNew, n ); 1382 } 1383 else if( *pEnd < *pTStt ) 1384 break; 1385 } 1386 return bChg; 1387 } 1388 1389 bool SwDoc::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo, 1390 sal_uInt16 nDelType ) 1391 { 1392 if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & eRedlineMode || 1393 !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() ) 1394 return sal_False; 1395 1396 sal_Bool bChg = sal_False; 1397 1398 if (bSaveInUndo && GetIDocumentUndoRedo().DoesUndo()) 1399 { 1400 SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange ); 1401 if( pUndo->GetRedlSaveCount() ) 1402 { 1403 GetIDocumentUndoRedo().AppendUndo(pUndo); 1404 } 1405 else 1406 delete pUndo; 1407 } 1408 1409 const SwPosition* pStt = rRange.Start(), 1410 * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark() 1411 : rRange.GetPoint(); 1412 sal_uInt16 n = 0; 1413 GetRedline( *pStt, &n ); 1414 for( ; n < pRedlineTbl->Count() ; ++n ) 1415 { 1416 SwRedline* pRedl = (*pRedlineTbl)[ n ]; 1417 if( USHRT_MAX != nDelType && nDelType != pRedl->GetType() ) 1418 continue; 1419 1420 SwPosition* pRStt = pRedl->Start(), 1421 * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark() 1422 : pRedl->GetPoint(); 1423 sal_Bool bDel = sal_False; 1424 switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) ) 1425 { 1426 case POS_EQUAL: 1427 case POS_OUTSIDE: 1428 bDel = sal_True; 1429 break; 1430 1431 case POS_OVERLAP_BEFORE: 1432 if( *pEnd == *pREnd ) 1433 bDel = sal_True; 1434 else 1435 { 1436 pRedl->InvalidateRange(); 1437 pRedl->SetStart( *pEnd, pRStt ); 1438 // neu einsortieren 1439 pRedlineTbl->Remove( n ); 1440 pRedlineTbl->Insert( pRedl ); 1441 --n; 1442 } 1443 break; 1444 1445 case POS_OVERLAP_BEHIND: 1446 if( *pStt == *pRStt ) 1447 bDel = sal_True; 1448 else 1449 { 1450 pRedl->InvalidateRange(); 1451 pRedl->SetEnd( *pStt, pREnd ); 1452 if( !pRedl->HasValidRange() ) 1453 { 1454 // neu einsortieren 1455 pRedlineTbl->Remove( n ); 1456 pRedlineTbl->Insert( pRedl ); 1457 --n; 1458 } 1459 } 1460 break; 1461 1462 case POS_INSIDE: 1463 { 1464 // der muss gesplittet werden 1465 pRedl->InvalidateRange(); 1466 if( *pRStt == *pStt ) 1467 { 1468 pRedl->SetStart( *pEnd, pRStt ); 1469 // neu einsortieren 1470 pRedlineTbl->Remove( n ); 1471 pRedlineTbl->Insert( pRedl ); 1472 --n; 1473 } 1474 else 1475 { 1476 SwRedline* pCpy; 1477 if( *pREnd != *pEnd ) 1478 { 1479 pCpy = new SwRedline( *pRedl ); 1480 pCpy->SetStart( *pEnd ); 1481 } 1482 else 1483 pCpy = 0; 1484 pRedl->SetEnd( *pStt, pREnd ); 1485 if( !pRedl->HasValidRange() ) 1486 { 1487 // neu einsortieren 1488 pRedlineTbl->Remove( pRedlineTbl->GetPos( pRedl )); 1489 pRedlineTbl->Insert( pRedl ); 1490 --n; 1491 } 1492 if( pCpy ) 1493 pRedlineTbl->Insert( pCpy ); 1494 } 1495 } 1496 break; 1497 1498 case POS_COLLIDE_END: 1499 case POS_BEFORE: 1500 n = pRedlineTbl->Count(); 1501 break; 1502 default: 1503 break; 1504 } 1505 1506 if( bDel ) 1507 { 1508 pRedl->InvalidateRange(); 1509 pRedlineTbl->DeleteAndDestroy( n-- ); 1510 bChg = sal_True; 1511 } 1512 } 1513 1514 if( bChg ) 1515 SetModified(); 1516 1517 return bChg; 1518 } 1519 1520 bool SwDoc::DeleteRedline( const SwStartNode& rNode, bool bSaveInUndo, 1521 sal_uInt16 nDelType ) 1522 { 1523 SwPaM aTemp(*rNode.EndOfSectionNode(), rNode); 1524 return DeleteRedline(aTemp, bSaveInUndo, nDelType); 1525 } 1526 1527 sal_uInt16 SwDoc::GetRedlinePos( const SwNode& rNd, sal_uInt16 nType ) const 1528 { 1529 const sal_uLong nNdIdx = rNd.GetIndex(); 1530 for( sal_uInt16 n = 0; n < pRedlineTbl->Count() ; ++n ) 1531 { 1532 const SwRedline* pTmp = (*pRedlineTbl)[ n ]; 1533 sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(), 1534 nMk = pTmp->GetMark()->nNode.GetIndex(); 1535 if( nPt < nMk ) { long nTmp = nMk; nMk = nPt; nPt = nTmp; } 1536 1537 if( ( USHRT_MAX == nType || nType == pTmp->GetType()) && 1538 nMk <= nNdIdx && nNdIdx <= nPt ) 1539 return n; 1540 1541 if( nMk > nNdIdx ) 1542 break; 1543 } 1544 return USHRT_MAX; 1545 } 1546 1547 const SwRedline* SwDoc::GetRedline( const SwPosition& rPos, 1548 sal_uInt16* pFndPos ) const 1549 { 1550 sal_uInt16 nO = pRedlineTbl->Count(), nM, nU = 0; 1551 if( nO > 0 ) 1552 { 1553 nO--; 1554 while( nU <= nO ) 1555 { 1556 nM = nU + ( nO - nU ) / 2; 1557 const SwRedline* pRedl = (*pRedlineTbl)[ nM ]; 1558 const SwPosition* pStt = pRedl->Start(); 1559 const SwPosition* pEnd = pStt == pRedl->GetPoint() 1560 ? pRedl->GetMark() 1561 : pRedl->GetPoint(); 1562 if( pEnd == pStt 1563 ? *pStt == rPos 1564 : ( *pStt <= rPos && rPos < *pEnd ) ) 1565 { 1566 /* #107318# returned wrong redline ???*/ 1567 while( nM && rPos == *(*pRedlineTbl)[ nM - 1 ]->End() && 1568 rPos == *(*pRedlineTbl)[ nM - 1 ]->Start() ) 1569 { 1570 --nM; 1571 pRedl = (*pRedlineTbl)[ nM ]; 1572 } 1573 1574 if( pFndPos ) 1575 *pFndPos = nM; 1576 return pRedl; 1577 } 1578 else if( *pEnd <= rPos ) 1579 nU = nM + 1; 1580 else if( nM == 0 ) 1581 { 1582 if( pFndPos ) 1583 *pFndPos = nU; 1584 return 0; 1585 } 1586 else 1587 nO = nM - 1; 1588 } 1589 } 1590 if( pFndPos ) 1591 *pFndPos = nU; 1592 return 0; 1593 } 1594 1595 typedef sal_Bool (*Fn_AcceptReject)( SwRedlineTbl& rArr, sal_uInt16& rPos, 1596 sal_Bool bCallDelete, 1597 const SwPosition* pSttRng, 1598 const SwPosition* pEndRng); 1599 1600 sal_Bool lcl_AcceptRedline( SwRedlineTbl& rArr, sal_uInt16& rPos, 1601 sal_Bool bCallDelete, 1602 const SwPosition* pSttRng = 0, 1603 const SwPosition* pEndRng = 0 ) 1604 { 1605 sal_Bool bRet = sal_True; 1606 SwRedline* pRedl = rArr[ rPos ]; 1607 SwPosition *pRStt = 0, *pREnd = 0; 1608 SwComparePosition eCmp = POS_OUTSIDE; 1609 if( pSttRng && pEndRng ) 1610 { 1611 pRStt = pRedl->Start(); 1612 pREnd = pRedl->End(); 1613 eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd ); 1614 } 1615 1616 pRedl->InvalidateRange(); 1617 1618 switch( pRedl->GetType() ) 1619 { 1620 case nsRedlineType_t::REDLINE_INSERT: 1621 case nsRedlineType_t::REDLINE_FORMAT: 1622 { 1623 sal_Bool bCheck = sal_False, bReplace = sal_False; 1624 switch( eCmp ) 1625 { 1626 case POS_INSIDE: 1627 if( *pSttRng == *pRStt ) 1628 pRedl->SetStart( *pEndRng, pRStt ); 1629 else 1630 { 1631 if( *pEndRng != *pREnd ) 1632 { 1633 // aufsplitten 1634 SwRedline* pNew = new SwRedline( *pRedl ); 1635 pNew->SetStart( *pEndRng ); 1636 rArr.Insert( pNew ); ++rPos; 1637 } 1638 pRedl->SetEnd( *pSttRng, pREnd ); 1639 bCheck = sal_True; 1640 } 1641 break; 1642 1643 case POS_OVERLAP_BEFORE: 1644 pRedl->SetStart( *pEndRng, pRStt ); 1645 bReplace = sal_True; 1646 break; 1647 1648 case POS_OVERLAP_BEHIND: 1649 pRedl->SetEnd( *pSttRng, pREnd ); 1650 bCheck = sal_True; 1651 break; 1652 1653 case POS_OUTSIDE: 1654 case POS_EQUAL: 1655 rArr.DeleteAndDestroy( rPos-- ); 1656 break; 1657 1658 default: 1659 bRet = sal_False; 1660 } 1661 1662 if( bReplace || ( bCheck && !pRedl->HasValidRange() )) 1663 { 1664 // neu einsortieren 1665 rArr.Remove( rArr.GetPos( pRedl )); 1666 rArr.Insert( pRedl ); 1667 } 1668 } 1669 break; 1670 case nsRedlineType_t::REDLINE_DELETE: 1671 { 1672 SwDoc& rDoc = *pRedl->GetDoc(); 1673 const SwPosition *pDelStt = 0, *pDelEnd = 0; 1674 sal_Bool bDelRedl = sal_False; 1675 switch( eCmp ) 1676 { 1677 case POS_INSIDE: 1678 if( bCallDelete ) 1679 { 1680 pDelStt = pSttRng; 1681 pDelEnd = pEndRng; 1682 } 1683 break; 1684 1685 case POS_OVERLAP_BEFORE: 1686 if( bCallDelete ) 1687 { 1688 pDelStt = pRStt; 1689 pDelEnd = pEndRng; 1690 } 1691 break; 1692 case POS_OVERLAP_BEHIND: 1693 if( bCallDelete ) 1694 { 1695 pDelStt = pREnd; 1696 pDelEnd = pSttRng; 1697 } 1698 break; 1699 1700 case POS_OUTSIDE: 1701 case POS_EQUAL: 1702 { 1703 rArr.Remove( rPos-- ); 1704 bDelRedl = sal_True; 1705 if( bCallDelete ) 1706 { 1707 pDelStt = pRedl->Start(); 1708 pDelEnd = pRedl->End(); 1709 } 1710 } 1711 break; 1712 default: 1713 bRet = sal_False; 1714 } 1715 1716 if( pDelStt && pDelEnd ) 1717 { 1718 SwPaM aPam( *pDelStt, *pDelEnd ); 1719 SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode(); 1720 SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode(); 1721 1722 if( bDelRedl ) 1723 delete pRedl; 1724 1725 RedlineMode_t eOld = rDoc.GetRedlineMode(); 1726 rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE))); 1727 1728 if( pCSttNd && pCEndNd ) 1729 rDoc.DeleteAndJoin( aPam ); 1730 else 1731 { 1732 rDoc.DeleteRange( aPam ); 1733 1734 if( pCSttNd && !pCEndNd ) 1735 { 1736 aPam.GetBound( sal_True ).nContent.Assign( 0, 0 ); 1737 aPam.GetBound( sal_False ).nContent.Assign( 0, 0 ); 1738 aPam.DeleteMark(); 1739 rDoc.DelFullPara( aPam ); 1740 } 1741 } 1742 rDoc.SetRedlineMode_intern( eOld ); 1743 } 1744 else if( bDelRedl ) 1745 delete pRedl; 1746 } 1747 break; 1748 1749 case nsRedlineType_t::REDLINE_FMTCOLL: 1750 rArr.DeleteAndDestroy( rPos-- ); 1751 break; 1752 1753 default: 1754 bRet = sal_False; 1755 } 1756 return bRet; 1757 } 1758 1759 sal_Bool lcl_RejectRedline( SwRedlineTbl& rArr, sal_uInt16& rPos, 1760 sal_Bool bCallDelete, 1761 const SwPosition* pSttRng = 0, 1762 const SwPosition* pEndRng = 0 ) 1763 { 1764 sal_Bool bRet = sal_True; 1765 SwRedline* pRedl = rArr[ rPos ]; 1766 SwPosition *pRStt = 0, *pREnd = 0; 1767 SwComparePosition eCmp = POS_OUTSIDE; 1768 if( pSttRng && pEndRng ) 1769 { 1770 pRStt = pRedl->Start(); 1771 pREnd = pRedl->End(); 1772 eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd ); 1773 } 1774 1775 pRedl->InvalidateRange(); 1776 1777 switch( pRedl->GetType() ) 1778 { 1779 case nsRedlineType_t::REDLINE_INSERT: 1780 { 1781 SwDoc& rDoc = *pRedl->GetDoc(); 1782 const SwPosition *pDelStt = 0, *pDelEnd = 0; 1783 sal_Bool bDelRedl = sal_False; 1784 switch( eCmp ) 1785 { 1786 case POS_INSIDE: 1787 if( bCallDelete ) 1788 { 1789 pDelStt = pSttRng; 1790 pDelEnd = pEndRng; 1791 } 1792 break; 1793 1794 case POS_OVERLAP_BEFORE: 1795 if( bCallDelete ) 1796 { 1797 pDelStt = pRStt; 1798 pDelEnd = pEndRng; 1799 } 1800 break; 1801 case POS_OVERLAP_BEHIND: 1802 if( bCallDelete ) 1803 { 1804 pDelStt = pREnd; 1805 pDelEnd = pSttRng; 1806 } 1807 break; 1808 case POS_OUTSIDE: 1809 case POS_EQUAL: 1810 { 1811 // dann den Bereich wieder loeschen 1812 rArr.Remove( rPos-- ); 1813 bDelRedl = sal_True; 1814 if( bCallDelete ) 1815 { 1816 pDelStt = pRedl->Start(); 1817 pDelEnd = pRedl->End(); 1818 } 1819 } 1820 break; 1821 1822 default: 1823 bRet = sal_False; 1824 } 1825 if( pDelStt && pDelEnd ) 1826 { 1827 SwPaM aPam( *pDelStt, *pDelEnd ); 1828 1829 SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode(); 1830 SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode(); 1831 1832 if( bDelRedl ) 1833 delete pRedl; 1834 1835 RedlineMode_t eOld = rDoc.GetRedlineMode(); 1836 rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE))); 1837 1838 if( pCSttNd && pCEndNd ) 1839 rDoc.DeleteAndJoin( aPam ); 1840 else 1841 { 1842 rDoc.DeleteRange( aPam ); 1843 1844 if( pCSttNd && !pCEndNd ) 1845 { 1846 aPam.GetBound( sal_True ).nContent.Assign( 0, 0 ); 1847 aPam.GetBound( sal_False ).nContent.Assign( 0, 0 ); 1848 aPam.DeleteMark(); 1849 rDoc.DelFullPara( aPam ); 1850 } 1851 } 1852 rDoc.SetRedlineMode_intern( eOld ); 1853 } 1854 else if( bDelRedl ) 1855 delete pRedl; 1856 } 1857 break; 1858 case nsRedlineType_t::REDLINE_DELETE: 1859 { 1860 SwRedline* pNew = 0; 1861 sal_Bool bCheck = sal_False, bReplace = sal_False; 1862 1863 switch( eCmp ) 1864 { 1865 case POS_INSIDE: 1866 { 1867 if( 1 < pRedl->GetStackCount() ) 1868 { 1869 pNew = new SwRedline( *pRedl ); 1870 pNew->PopData(); 1871 } 1872 if( *pSttRng == *pRStt ) 1873 { 1874 pRedl->SetStart( *pEndRng, pRStt ); 1875 bReplace = sal_True; 1876 if( pNew ) 1877 pNew->SetEnd( *pEndRng ); 1878 } 1879 else 1880 { 1881 if( *pEndRng != *pREnd ) 1882 { 1883 // aufsplitten 1884 SwRedline* pCpy = new SwRedline( *pRedl ); 1885 pCpy->SetStart( *pEndRng ); 1886 rArr.Insert( pCpy ); ++rPos; 1887 if( pNew ) 1888 pNew->SetEnd( *pEndRng ); 1889 } 1890 1891 pRedl->SetEnd( *pSttRng, pREnd ); 1892 bCheck = sal_True; 1893 if( pNew ) 1894 pNew->SetStart( *pSttRng ); 1895 } 1896 } 1897 break; 1898 1899 case POS_OVERLAP_BEFORE: 1900 if( 1 < pRedl->GetStackCount() ) 1901 { 1902 pNew = new SwRedline( *pRedl ); 1903 pNew->PopData(); 1904 } 1905 pRedl->SetStart( *pEndRng, pRStt ); 1906 bReplace = sal_True; 1907 if( pNew ) 1908 pNew->SetEnd( *pEndRng ); 1909 break; 1910 1911 case POS_OVERLAP_BEHIND: 1912 if( 1 < pRedl->GetStackCount() ) 1913 { 1914 pNew = new SwRedline( *pRedl ); 1915 pNew->PopData(); 1916 } 1917 pRedl->SetEnd( *pSttRng, pREnd ); 1918 bCheck = sal_True; 1919 if( pNew ) 1920 pNew->SetStart( *pSttRng ); 1921 break; 1922 1923 case POS_OUTSIDE: 1924 case POS_EQUAL: 1925 if( !pRedl->PopData() ) 1926 // das RedlineObject loeschen reicht 1927 rArr.DeleteAndDestroy( rPos-- ); 1928 break; 1929 1930 default: 1931 bRet = sal_False; 1932 } 1933 1934 if( pNew ) 1935 { 1936 rArr.Insert( pNew ); ++rPos; 1937 } 1938 1939 if( bReplace || ( bCheck && !pRedl->HasValidRange() )) 1940 { 1941 // neu einsortieren 1942 rArr.Remove( rArr.GetPos( pRedl )); 1943 rArr.Insert( pRedl ); 1944 } 1945 } 1946 break; 1947 1948 case nsRedlineType_t::REDLINE_FORMAT: 1949 case nsRedlineType_t::REDLINE_FMTCOLL: 1950 { 1951 if( pRedl->GetExtraData() ) 1952 pRedl->GetExtraData()->Reject( *pRedl ); 1953 rArr.DeleteAndDestroy( rPos-- ); 1954 } 1955 break; 1956 1957 default: 1958 bRet = sal_False; 1959 } 1960 return bRet; 1961 } 1962 1963 1964 const SwRedline* lcl_FindCurrRedline( const SwPosition& rSttPos, 1965 sal_uInt16& rPos, 1966 sal_Bool bNext = sal_True ) 1967 { 1968 const SwRedline* pFnd = 0; 1969 const SwRedlineTbl& rArr = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl(); 1970 for( ; rPos < rArr.Count() ; ++rPos ) 1971 { 1972 const SwRedline* pTmp = rArr[ rPos ]; 1973 if( pTmp->HasMark() && pTmp->IsVisible() ) 1974 { 1975 const SwPosition* pRStt = pTmp->Start(), 1976 * pREnd = pRStt == pTmp->GetPoint() ? pTmp->GetMark() 1977 : pTmp->GetPoint(); 1978 if( bNext ? *pRStt <= rSttPos : *pRStt < rSttPos ) 1979 { 1980 if( bNext ? *pREnd > rSttPos : *pREnd >= rSttPos ) 1981 { 1982 pFnd = pTmp; 1983 break; 1984 } 1985 } 1986 else 1987 break; 1988 } 1989 } 1990 return pFnd; 1991 } 1992 1993 // #111827# 1994 int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject, 1995 SwRedlineTbl& rArr, sal_Bool bCallDelete, 1996 const SwPaM& rPam) 1997 { 1998 sal_uInt16 n = 0; 1999 int nCount = 0; // #111827# 2000 2001 const SwPosition* pStt = rPam.Start(), 2002 * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark() 2003 : rPam.GetPoint(); 2004 const SwRedline* pFnd = lcl_FindCurrRedline( *pStt, n, sal_True ); 2005 if( pFnd && // neu ein Teil davon? 2006 ( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd )) 2007 { 2008 // dann nur die TeilSelektion aufheben 2009 if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd )) 2010 nCount++; // #111827# 2011 ++n; 2012 } 2013 2014 for( ; n < rArr.Count(); ++n ) 2015 { 2016 SwRedline* pTmp = rArr[ n ]; 2017 if( pTmp->HasMark() && pTmp->IsVisible() ) 2018 { 2019 if( *pTmp->End() <= *pEnd ) 2020 { 2021 if( (*fn_AcceptReject)( rArr, n, bCallDelete, 0, 0 )) 2022 nCount++; // #111827# 2023 } 2024 else 2025 { 2026 if( *pTmp->Start() < *pEnd ) 2027 { 2028 // dann nur in der TeilSelektion aufheben 2029 if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd )) 2030 nCount++; // #111827# 2031 } 2032 break; 2033 } 2034 } 2035 } 2036 return nCount; // #111827# 2037 } 2038 2039 void lcl_AdjustRedlineRange( SwPaM& rPam ) 2040 { 2041 // die Selektion steht nur im ContentBereich. Wenn es aber Redlines 2042 // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die 2043 // die Selection auf diese 2044 SwPosition* pStt = rPam.Start(), 2045 * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark() 2046 : rPam.GetPoint(); 2047 SwDoc* pDoc = rPam.GetDoc(); 2048 if( !pStt->nContent.GetIndex() && 2049 !pDoc->GetNodes()[ pStt->nNode.GetIndex() - 1 ]->IsCntntNode() ) 2050 { 2051 const SwRedline* pRedl = pDoc->GetRedline( *pStt, 0 ); 2052 if( pRedl ) 2053 { 2054 const SwPosition* pRStt = pRedl->Start(); 2055 if( !pRStt->nContent.GetIndex() && pRStt->nNode.GetIndex() == 2056 pStt->nNode.GetIndex() - 1 ) 2057 *pStt = *pRStt; 2058 } 2059 } 2060 if( pEnd->nNode.GetNode().IsCntntNode() && 2061 !pDoc->GetNodes()[ pEnd->nNode.GetIndex() + 1 ]->IsCntntNode() && 2062 pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() ) 2063 { 2064 const SwRedline* pRedl = pDoc->GetRedline( *pEnd, 0 ); 2065 if( pRedl ) 2066 { 2067 const SwPosition* pREnd = pRedl->End(); 2068 if( !pREnd->nContent.GetIndex() && pREnd->nNode.GetIndex() == 2069 pEnd->nNode.GetIndex() + 1 ) 2070 *pEnd = *pREnd; 2071 } 2072 } 2073 } 2074 2075 2076 bool SwDoc::AcceptRedline( sal_uInt16 nPos, bool bCallDelete ) 2077 { 2078 sal_Bool bRet = sal_False; 2079 2080 // aufjedenfall auf sichtbar umschalten 2081 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) != 2082 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) ) 2083 SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode)); 2084 2085 SwRedline* pTmp = (*pRedlineTbl)[ nPos ]; 2086 if( pTmp->HasMark() && pTmp->IsVisible() ) 2087 { 2088 if (GetIDocumentUndoRedo().DoesUndo()) 2089 { 2090 // #111827# 2091 SwRewriter aRewriter; 2092 2093 aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr()); 2094 GetIDocumentUndoRedo().StartUndo(UNDO_ACCEPT_REDLINE, &aRewriter); 2095 } 2096 2097 int nLoopCnt = 2; 2098 sal_uInt16 nSeqNo = pTmp->GetSeqNo(); 2099 2100 do { 2101 2102 if (GetIDocumentUndoRedo().DoesUndo()) 2103 { 2104 SwUndo *const pUndo( new SwUndoAcceptRedline(*pTmp) ); 2105 GetIDocumentUndoRedo().AppendUndo(pUndo); 2106 } 2107 2108 bRet |= lcl_AcceptRedline( *pRedlineTbl, nPos, bCallDelete ); 2109 2110 if( nSeqNo ) 2111 { 2112 if( USHRT_MAX == nPos ) 2113 nPos = 0; 2114 sal_uInt16 nFndPos = 2 == nLoopCnt 2115 ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos ) 2116 : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ); 2117 if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) && 2118 USHRT_MAX != ( nFndPos = 2119 pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) ) 2120 pTmp = (*pRedlineTbl)[ nPos = nFndPos ]; 2121 else 2122 nLoopCnt = 0; 2123 } 2124 else 2125 nLoopCnt = 0; 2126 2127 } while( nLoopCnt ); 2128 2129 if( bRet ) 2130 { 2131 CompressRedlines(); 2132 SetModified(); 2133 } 2134 2135 if (GetIDocumentUndoRedo().DoesUndo()) 2136 { 2137 GetIDocumentUndoRedo().EndUndo(UNDO_END, 0); 2138 } 2139 } 2140 return bRet; 2141 } 2142 2143 bool SwDoc::AcceptRedline( const SwPaM& rPam, bool bCallDelete ) 2144 { 2145 // aufjedenfall auf sichtbar umschalten 2146 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) != 2147 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) ) 2148 SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode)); 2149 2150 // die Selektion steht nur im ContentBereich. Wenn es aber Redlines 2151 // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die 2152 // die Selection auf diese 2153 SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() ); 2154 lcl_AdjustRedlineRange( aPam ); 2155 2156 if (GetIDocumentUndoRedo().DoesUndo()) 2157 { 2158 GetIDocumentUndoRedo().StartUndo( UNDO_ACCEPT_REDLINE, NULL ); 2159 GetIDocumentUndoRedo().AppendUndo( new SwUndoAcceptRedline( aPam )); 2160 } 2161 2162 // #111827# 2163 int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *pRedlineTbl, 2164 bCallDelete, aPam ); 2165 if( nRet > 0 ) 2166 { 2167 CompressRedlines(); 2168 SetModified(); 2169 } 2170 if (GetIDocumentUndoRedo().DoesUndo()) 2171 { 2172 // #111827# 2173 String aTmpStr; 2174 2175 { 2176 SwRewriter aRewriter; 2177 aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet)); 2178 aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES))); 2179 } 2180 2181 SwRewriter aRewriter; 2182 aRewriter.AddRule(UNDO_ARG1, aTmpStr); 2183 2184 GetIDocumentUndoRedo().EndUndo( UNDO_ACCEPT_REDLINE, &aRewriter ); 2185 } 2186 return nRet != 0; 2187 } 2188 2189 bool SwDoc::RejectRedline( sal_uInt16 nPos, bool bCallDelete ) 2190 { 2191 sal_Bool bRet = sal_False; 2192 2193 // aufjedenfall auf sichtbar umschalten 2194 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) != 2195 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) ) 2196 SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode)); 2197 2198 SwRedline* pTmp = (*pRedlineTbl)[ nPos ]; 2199 if( pTmp->HasMark() && pTmp->IsVisible() ) 2200 { 2201 if (GetIDocumentUndoRedo().DoesUndo()) 2202 { 2203 // #111827# 2204 SwRewriter aRewriter; 2205 2206 aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr()); 2207 GetIDocumentUndoRedo().StartUndo(UNDO_REJECT_REDLINE, &aRewriter); 2208 } 2209 2210 int nLoopCnt = 2; 2211 sal_uInt16 nSeqNo = pTmp->GetSeqNo(); 2212 2213 do { 2214 2215 if (GetIDocumentUndoRedo().DoesUndo()) 2216 { 2217 SwUndo *const pUndo( new SwUndoRejectRedline( *pTmp ) ); 2218 GetIDocumentUndoRedo().AppendUndo(pUndo); 2219 } 2220 2221 bRet |= lcl_RejectRedline( *pRedlineTbl, nPos, bCallDelete ); 2222 2223 if( nSeqNo ) 2224 { 2225 if( USHRT_MAX == nPos ) 2226 nPos = 0; 2227 sal_uInt16 nFndPos = 2 == nLoopCnt 2228 ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos ) 2229 : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ); 2230 if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) && 2231 USHRT_MAX != ( nFndPos = 2232 pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) ) 2233 pTmp = (*pRedlineTbl)[ nPos = nFndPos ]; 2234 else 2235 nLoopCnt = 0; 2236 } 2237 else 2238 nLoopCnt = 0; 2239 2240 } while( nLoopCnt ); 2241 2242 if( bRet ) 2243 { 2244 CompressRedlines(); 2245 SetModified(); 2246 } 2247 2248 if (GetIDocumentUndoRedo().DoesUndo()) 2249 { 2250 GetIDocumentUndoRedo().EndUndo(UNDO_END, 0); 2251 } 2252 } 2253 return bRet; 2254 } 2255 2256 bool SwDoc::RejectRedline( const SwPaM& rPam, bool bCallDelete ) 2257 { 2258 // aufjedenfall auf sichtbar umschalten 2259 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) != 2260 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) ) 2261 SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode)); 2262 2263 // die Selektion steht nur im ContentBereich. Wenn es aber Redlines 2264 // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die 2265 // die Selection auf diese 2266 SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() ); 2267 lcl_AdjustRedlineRange( aPam ); 2268 2269 if (GetIDocumentUndoRedo().DoesUndo()) 2270 { 2271 GetIDocumentUndoRedo().StartUndo( UNDO_REJECT_REDLINE, NULL ); 2272 GetIDocumentUndoRedo().AppendUndo( new SwUndoRejectRedline(aPam) ); 2273 } 2274 2275 // #111827# 2276 int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *pRedlineTbl, 2277 bCallDelete, aPam ); 2278 if( nRet > 0 ) 2279 { 2280 CompressRedlines(); 2281 SetModified(); 2282 } 2283 if (GetIDocumentUndoRedo().DoesUndo()) 2284 { 2285 // #111827# 2286 String aTmpStr; 2287 2288 { 2289 SwRewriter aRewriter; 2290 aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet)); 2291 aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES))); 2292 } 2293 2294 SwRewriter aRewriter; 2295 aRewriter.AddRule(UNDO_ARG1, aTmpStr); 2296 2297 GetIDocumentUndoRedo().EndUndo( UNDO_REJECT_REDLINE, &aRewriter ); 2298 } 2299 2300 return nRet != 0; 2301 } 2302 2303 const SwRedline* SwDoc::SelNextRedline( SwPaM& rPam ) const 2304 { 2305 rPam.DeleteMark(); 2306 rPam.SetMark(); 2307 2308 SwPosition& rSttPos = *rPam.GetPoint(); 2309 SwPosition aSavePos( rSttPos ); 2310 sal_Bool bRestart; 2311 2312 // sollte die StartPos auf dem letzen gueligen ContentNode stehen, 2313 // dann aufjedenfall das naechste Redline nehmen 2314 sal_uInt16 n = 0; 2315 const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_True ); 2316 if( pFnd ) 2317 { 2318 const SwPosition* pEnd = pFnd->End(); 2319 if( !pEnd->nNode.GetNode().IsCntntNode() ) 2320 { 2321 SwNodeIndex aTmp( pEnd->nNode ); 2322 SwCntntNode* pCNd = GetNodes().GoPrevSection( &aTmp ); 2323 if( !pCNd || ( aTmp == rSttPos.nNode && 2324 pCNd->Len() == rSttPos.nContent.GetIndex() )) 2325 pFnd = 0; 2326 } 2327 if( pFnd ) 2328 rSttPos = *pFnd->End(); 2329 } 2330 2331 do { 2332 bRestart = sal_False; 2333 2334 for( ; !pFnd && n < pRedlineTbl->Count(); ++n ) 2335 { 2336 pFnd = (*pRedlineTbl)[ n ]; 2337 if( pFnd->HasMark() && pFnd->IsVisible() ) 2338 { 2339 *rPam.GetMark() = *pFnd->Start(); 2340 rSttPos = *pFnd->End(); 2341 break; 2342 } 2343 else 2344 pFnd = 0; 2345 } 2346 2347 if( pFnd ) 2348 { 2349 // alle vom gleichen Typ und Author, die hinter einander liegen 2350 // zu einer Selektion zusammenfassen. 2351 const SwPosition* pPrevEnd = pFnd->End(); 2352 while( ++n < pRedlineTbl->Count() ) 2353 { 2354 const SwRedline* pTmp = (*pRedlineTbl)[ n ]; 2355 if( pTmp->HasMark() && pTmp->IsVisible() ) 2356 { 2357 const SwPosition *pRStt; 2358 if( pFnd->GetType() == pTmp->GetType() && 2359 pFnd->GetAuthor() == pTmp->GetAuthor() && 2360 ( *pPrevEnd == *( pRStt = pTmp->Start() ) || 2361 IsPrevPos( *pPrevEnd, *pRStt )) ) 2362 { 2363 pPrevEnd = pTmp->End(); 2364 rSttPos = *pPrevEnd; 2365 } 2366 else 2367 break; 2368 } 2369 } 2370 } 2371 2372 if( pFnd ) 2373 { 2374 const SwRedline* pSaveFnd = pFnd; 2375 2376 SwCntntNode* pCNd; 2377 SwNodeIndex* pIdx = &rPam.GetMark()->nNode; 2378 if( !pIdx->GetNode().IsCntntNode() && 2379 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) ) 2380 { 2381 if( *pIdx <= rPam.GetPoint()->nNode ) 2382 rPam.GetMark()->nContent.Assign( pCNd, 0 ); 2383 else 2384 pFnd = 0; 2385 } 2386 2387 if( pFnd ) 2388 { 2389 pIdx = &rPam.GetPoint()->nNode; 2390 if( !pIdx->GetNode().IsCntntNode() && 2391 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) ) 2392 { 2393 if( *pIdx >= rPam.GetMark()->nNode ) 2394 rPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); 2395 else 2396 pFnd = 0; 2397 } 2398 } 2399 2400 if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() ) 2401 { 2402 if( n < pRedlineTbl->Count() ) 2403 { 2404 bRestart = sal_True; 2405 *rPam.GetPoint() = *pSaveFnd->End(); 2406 } 2407 else 2408 { 2409 rPam.DeleteMark(); 2410 *rPam.GetPoint() = aSavePos; 2411 } 2412 pFnd = 0; 2413 } 2414 } 2415 } while( bRestart ); 2416 2417 return pFnd; 2418 } 2419 2420 const SwRedline* SwDoc::SelPrevRedline( SwPaM& rPam ) const 2421 { 2422 rPam.DeleteMark(); 2423 rPam.SetMark(); 2424 2425 SwPosition& rSttPos = *rPam.GetPoint(); 2426 SwPosition aSavePos( rSttPos ); 2427 sal_Bool bRestart; 2428 2429 // sollte die StartPos auf dem ersten gueligen ContentNode stehen, 2430 // dann aufjedenfall das vorherige Redline nehmen 2431 sal_uInt16 n = 0; 2432 const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_False ); 2433 if( pFnd ) 2434 { 2435 const SwPosition* pStt = pFnd->Start(); 2436 if( !pStt->nNode.GetNode().IsCntntNode() ) 2437 { 2438 SwNodeIndex aTmp( pStt->nNode ); 2439 SwCntntNode* pCNd = GetNodes().GoNextSection( &aTmp ); 2440 if( !pCNd || ( aTmp == rSttPos.nNode && 2441 !rSttPos.nContent.GetIndex() )) 2442 pFnd = 0; 2443 } 2444 if( pFnd ) 2445 rSttPos = *pFnd->Start(); 2446 } 2447 2448 do { 2449 bRestart = sal_False; 2450 2451 while( !pFnd && 0 < n ) 2452 { 2453 pFnd = (*pRedlineTbl)[ --n ]; 2454 if( pFnd->HasMark() && pFnd->IsVisible() ) 2455 { 2456 *rPam.GetMark() = *pFnd->End(); 2457 rSttPos = *pFnd->Start(); 2458 } 2459 else 2460 pFnd = 0; 2461 } 2462 2463 if( pFnd ) 2464 { 2465 // alle vom gleichen Typ und Author, die hinter einander liegen 2466 // zu einer Selektion zusammenfassen. 2467 const SwPosition* pNextStt = pFnd->Start(); 2468 while( 0 < n ) 2469 { 2470 const SwRedline* pTmp = (*pRedlineTbl)[ --n ]; 2471 if( pTmp->HasMark() && pTmp->IsVisible() ) 2472 { 2473 const SwPosition *pREnd; 2474 if( pFnd->GetType() == pTmp->GetType() && 2475 pFnd->GetAuthor() == pTmp->GetAuthor() && 2476 ( *pNextStt == *( pREnd = pTmp->End() ) || 2477 IsPrevPos( *pREnd, *pNextStt )) ) 2478 { 2479 pNextStt = pTmp->Start(); 2480 rSttPos = *pNextStt; 2481 } 2482 else 2483 { 2484 ++n; 2485 break; 2486 } 2487 } 2488 } 2489 } 2490 2491 if( pFnd ) 2492 { 2493 const SwRedline* pSaveFnd = pFnd; 2494 2495 SwCntntNode* pCNd; 2496 SwNodeIndex* pIdx = &rPam.GetMark()->nNode; 2497 if( !pIdx->GetNode().IsCntntNode() && 2498 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) ) 2499 { 2500 if( *pIdx >= rPam.GetPoint()->nNode ) 2501 rPam.GetMark()->nContent.Assign( pCNd, pCNd->Len() ); 2502 else 2503 pFnd = 0; 2504 } 2505 2506 if( pFnd ) 2507 { 2508 pIdx = &rPam.GetPoint()->nNode; 2509 if( !pIdx->GetNode().IsCntntNode() && 2510 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) ) 2511 { 2512 if( *pIdx <= rPam.GetMark()->nNode ) 2513 rPam.GetPoint()->nContent.Assign( pCNd, 0 ); 2514 else 2515 pFnd = 0; 2516 } 2517 } 2518 2519 if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() ) 2520 { 2521 if( n ) 2522 { 2523 bRestart = sal_True; 2524 *rPam.GetPoint() = *pSaveFnd->Start(); 2525 } 2526 else 2527 { 2528 rPam.DeleteMark(); 2529 *rPam.GetPoint() = aSavePos; 2530 } 2531 pFnd = 0; 2532 } 2533 } 2534 } while( bRestart ); 2535 2536 return pFnd; 2537 } 2538 2539 // Kommentar am Redline setzen 2540 bool SwDoc::SetRedlineComment( const SwPaM& rPaM, const String& rS ) 2541 { 2542 sal_Bool bRet = sal_False; 2543 const SwPosition* pStt = rPaM.Start(), 2544 * pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark() 2545 : rPaM.GetPoint(); 2546 sal_uInt16 n = 0; 2547 if( lcl_FindCurrRedline( *pStt, n, sal_True ) ) 2548 { 2549 for( ; n < pRedlineTbl->Count(); ++n ) 2550 { 2551 bRet = sal_True; 2552 SwRedline* pTmp = (*pRedlineTbl)[ n ]; 2553 if( pStt != pEnd && *pTmp->Start() > *pEnd ) 2554 break; 2555 2556 pTmp->SetComment( rS ); 2557 if( *pTmp->End() >= *pEnd ) 2558 break; 2559 } 2560 } 2561 if( bRet ) 2562 SetModified(); 2563 2564 return bRet; 2565 } 2566 2567 // legt gebenenfalls einen neuen Author an 2568 sal_uInt16 SwDoc::GetRedlineAuthor() 2569 { 2570 return SW_MOD()->GetRedlineAuthor(); 2571 } 2572 2573 // fuer die Reader usw. - neuen Author in die Tabelle eintragen 2574 sal_uInt16 SwDoc::InsertRedlineAuthor( const String& rNew ) 2575 { 2576 return SW_MOD()->InsertRedlineAuthor(rNew); 2577 } 2578 2579 void SwDoc::UpdateRedlineAttr() 2580 { 2581 const SwRedlineTbl& rTbl = GetRedlineTbl(); 2582 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 2583 { 2584 SwRedline* pRedl = rTbl[ n ]; 2585 if( pRedl->IsVisible() ) 2586 pRedl->InvalidateRange(); 2587 } 2588 } 2589 2590 // setze Kommentar-Text fuers Redline, das dann per AppendRedline 2591 // hereinkommt. Wird vom Autoformat benutzt. 0-Pointer setzt den Modus 2592 // wieder zurueck. Pointer wird nicht kopiert, muss also gueltig bleiben! 2593 void SwDoc::SetAutoFmtRedlineComment( const String* pTxt, sal_uInt16 nSeqNo ) 2594 { 2595 mbIsAutoFmtRedline = 0 != pTxt; 2596 if( pTxt ) 2597 { 2598 if( !pAutoFmtRedlnComment ) 2599 pAutoFmtRedlnComment = new String( *pTxt ); 2600 else 2601 *pAutoFmtRedlnComment = *pTxt; 2602 } 2603 else if( pAutoFmtRedlnComment ) 2604 delete pAutoFmtRedlnComment, pAutoFmtRedlnComment = 0; 2605 2606 nAutoFmtRedlnCommentNo = nSeqNo; 2607 } 2608 2609 void SwDoc::SetRedlinePassword( 2610 /*[in]*/const uno::Sequence <sal_Int8>& rNewPassword) 2611 { 2612 aRedlinePasswd = rNewPassword; 2613 SetModified(); 2614 } 2615 2616 /* */ 2617 2618 sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_Bool bIns ) 2619 { 2620 sal_Bool bRet = sal_False; 2621 if( p->HasValidRange() ) 2622 { 2623 bRet = _SwRedlineTbl::Insert( p ); 2624 p->CallDisplayFunc(); 2625 } 2626 else if( bIns ) 2627 bRet = InsertWithValidRanges( p ); 2628 else 2629 { 2630 ASSERT( !this, "Redline: falscher Bereich" ); 2631 } 2632 return bRet; 2633 } 2634 2635 sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_uInt16& rP, sal_Bool bIns ) 2636 { 2637 sal_Bool bRet = sal_False; 2638 if( p->HasValidRange() ) 2639 { 2640 bRet = _SwRedlineTbl::Insert( p, rP ); 2641 p->CallDisplayFunc(); 2642 } 2643 else if( bIns ) 2644 bRet = InsertWithValidRanges( p, &rP ); 2645 else 2646 { 2647 ASSERT( !this, "Redline: falscher Bereich" ); 2648 } 2649 return bRet; 2650 } 2651 2652 sal_Bool SwRedlineTbl::InsertWithValidRanges( SwRedlinePtr& p, sal_uInt16* pInsPos ) 2653 { 2654 // erzeuge aus den Selektion gueltige "Teilbereiche". 2655 sal_Bool bAnyIns = sal_False; 2656 SwPosition* pStt = p->Start(), 2657 * pEnd = pStt == p->GetPoint() ? p->GetMark() : p->GetPoint(); 2658 SwPosition aNewStt( *pStt ); 2659 SwNodes& rNds = aNewStt.nNode.GetNodes(); 2660 SwCntntNode* pC; 2661 2662 if( !aNewStt.nNode.GetNode().IsCntntNode() ) 2663 { 2664 pC = rNds.GoNext( &aNewStt.nNode ); 2665 if( pC ) 2666 aNewStt.nContent.Assign( pC, 0 ); 2667 else 2668 aNewStt.nNode = rNds.GetEndOfContent(); 2669 } 2670 2671 SwRedline* pNew = 0; 2672 sal_uInt16 nInsPos; 2673 2674 if( aNewStt < *pEnd ) 2675 do { 2676 if( !pNew ) 2677 pNew = new SwRedline( p->GetRedlineData(), aNewStt ); 2678 else 2679 { 2680 pNew->DeleteMark(); 2681 *pNew->GetPoint() = aNewStt; 2682 } 2683 2684 pNew->SetMark(); 2685 GoEndSection( pNew->GetPoint() ); 2686 // i60396: If the redlines starts before a table but the table is the last member 2687 // of the section, the GoEndSection will end inside the table. 2688 // This will result in an incorrect redline, so we've to go back 2689 SwNode* pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode(); 2690 // We end in a table when pTab != 0 2691 if( pTab && !pNew->GetMark()->nNode.GetNode().StartOfSectionNode()->FindTableNode() ) 2692 { // but our Mark was outside the table => Correction 2693 do 2694 { 2695 // We want to be before the table 2696 *pNew->GetPoint() = SwPosition(*pTab); 2697 pC = GoPreviousNds( &pNew->GetPoint()->nNode, sal_False ); // here we are. 2698 if( pC ) 2699 pNew->GetPoint()->nContent.Assign( pC, 0 ); 2700 pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode(); 2701 }while( pTab ); // If there is another table we have to repeat our step backwards 2702 } 2703 2704 if( *pNew->GetPoint() > *pEnd ) 2705 { 2706 pC = 0; 2707 if( aNewStt.nNode != pEnd->nNode ) 2708 do { 2709 SwNode& rCurNd = aNewStt.nNode.GetNode(); 2710 if( rCurNd.IsStartNode() ) 2711 { 2712 if( rCurNd.EndOfSectionIndex() < pEnd->nNode.GetIndex() ) 2713 aNewStt.nNode = *rCurNd.EndOfSectionNode(); 2714 else 2715 break; 2716 } 2717 else if( rCurNd.IsCntntNode() ) 2718 pC = rCurNd.GetCntntNode(); 2719 aNewStt.nNode++; 2720 } while( aNewStt.nNode.GetIndex() < pEnd->nNode.GetIndex() ); 2721 2722 if( aNewStt.nNode == pEnd->nNode ) 2723 aNewStt.nContent = pEnd->nContent; 2724 else if( pC ) 2725 { 2726 aNewStt.nNode = *pC; 2727 aNewStt.nContent.Assign( pC, pC->Len() ); 2728 } 2729 2730 if( aNewStt <= *pEnd ) 2731 *pNew->GetPoint() = aNewStt; 2732 } 2733 else 2734 aNewStt = *pNew->GetPoint(); 2735 #ifdef DEBUG 2736 CheckPosition( pNew->GetPoint(), pNew->GetMark() ); 2737 #endif 2738 if( *pNew->GetPoint() != *pNew->GetMark() && 2739 _SwRedlineTbl::Insert( pNew, nInsPos ) ) 2740 { 2741 pNew->CallDisplayFunc(); 2742 bAnyIns = sal_True; 2743 pNew = 0; 2744 if( pInsPos && *pInsPos < nInsPos ) 2745 *pInsPos = nInsPos; 2746 } 2747 2748 if( aNewStt >= *pEnd || 2749 0 == (pC = rNds.GoNext( &aNewStt.nNode )) ) 2750 break; 2751 2752 aNewStt.nContent.Assign( pC, 0 ); 2753 2754 } while( aNewStt < *pEnd ); 2755 2756 delete pNew; 2757 delete p, p = 0; 2758 return bAnyIns; 2759 } 2760 2761 void SwRedlineTbl::Remove( sal_uInt16 nP, sal_uInt16 nL ) 2762 { 2763 SwDoc* pDoc = 0; 2764 if( !nP && nL && nL == _SwRedlineTbl::Count() ) 2765 pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc(); 2766 2767 _SwRedlineTbl::Remove( nP, nL ); 2768 2769 ViewShell* pSh; 2770 if( pDoc && !pDoc->IsInDtor() && 2771 0 != ( pSh = pDoc->GetCurrentViewShell()) ) //swmod 071108//swmod 071225 2772 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) ); 2773 } 2774 2775 void SwRedlineTbl::DeleteAndDestroy( sal_uInt16 nP, sal_uInt16 nL ) 2776 { 2777 SwDoc* pDoc = 0; 2778 if( !nP && nL && nL == _SwRedlineTbl::Count() ) 2779 pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc(); 2780 2781 _SwRedlineTbl::DeleteAndDestroy( nP, nL ); 2782 2783 ViewShell* pSh; 2784 if( pDoc && !pDoc->IsInDtor() && 2785 0 != ( pSh = pDoc->GetCurrentViewShell() ) ) //swmod 071108//swmod 071225 2786 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) ); 2787 } 2788 2789 // suche den naechsten oder vorherigen Redline mit dergleichen Seq.No 2790 // Mit dem Lookahead kann die Suche eingeschraenkt werden. 0 oder 2791 // USHRT_MAX suchen im gesamten Array. 2792 sal_uInt16 SwRedlineTbl::FindNextOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const 2793 { 2794 return nSttPos + 1 < _SwRedlineTbl::Count() 2795 ? FindNextSeqNo( _SwRedlineTbl::GetObject( nSttPos ) 2796 ->GetSeqNo(), nSttPos+1, nLookahead ) 2797 : USHRT_MAX; 2798 } 2799 2800 sal_uInt16 SwRedlineTbl::FindPrevOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const 2801 { 2802 return nSttPos ? FindPrevSeqNo( _SwRedlineTbl::GetObject( 2803 nSttPos )->GetSeqNo(), 2804 nSttPos-1, nLookahead ) 2805 : USHRT_MAX; 2806 } 2807 2808 sal_uInt16 SwRedlineTbl::FindNextSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos, 2809 sal_uInt16 nLookahead ) const 2810 { 2811 sal_uInt16 nRet = USHRT_MAX, nEnd; 2812 if( nSeqNo && nSttPos < _SwRedlineTbl::Count() ) 2813 { 2814 nEnd = _SwRedlineTbl::Count(); 2815 if( nLookahead && USHRT_MAX != nLookahead && 2816 nSttPos + nLookahead < _SwRedlineTbl::Count() ) 2817 nEnd = nSttPos + nLookahead; 2818 2819 for( ; nSttPos < nEnd; ++nSttPos ) 2820 if( nSeqNo == _SwRedlineTbl::GetObject( nSttPos )->GetSeqNo() ) 2821 { 2822 nRet = nSttPos; 2823 break; 2824 } 2825 } 2826 return nRet; 2827 } 2828 2829 sal_uInt16 SwRedlineTbl::FindPrevSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos, 2830 sal_uInt16 nLookahead ) const 2831 { 2832 sal_uInt16 nRet = USHRT_MAX, nEnd; 2833 if( nSeqNo && nSttPos < _SwRedlineTbl::Count() ) 2834 { 2835 nEnd = 0; 2836 if( nLookahead && USHRT_MAX != nLookahead && nSttPos > nLookahead ) 2837 nEnd = nSttPos - nLookahead; 2838 2839 ++nSttPos; 2840 while( nSttPos > nEnd ) 2841 if( nSeqNo == _SwRedlineTbl::GetObject( --nSttPos )->GetSeqNo() ) 2842 { 2843 nRet = nSttPos; 2844 break; 2845 } 2846 } 2847 return nRet; 2848 } 2849 2850 /* */ 2851 2852 SwRedlineExtraData::~SwRedlineExtraData() 2853 { 2854 } 2855 2856 void SwRedlineExtraData::Accept( SwPaM& ) const 2857 { 2858 } 2859 2860 void SwRedlineExtraData::Reject( SwPaM& ) const 2861 { 2862 } 2863 2864 int SwRedlineExtraData::operator == ( const SwRedlineExtraData& ) const 2865 { 2866 return sal_False; 2867 } 2868 2869 2870 SwRedlineExtraData_FmtColl::SwRedlineExtraData_FmtColl( const String& rColl, 2871 sal_uInt16 nPoolFmtId, 2872 const SfxItemSet* pItemSet ) 2873 : sFmtNm(rColl), pSet(0), nPoolId(nPoolFmtId) 2874 { 2875 if( pItemSet && pItemSet->Count() ) 2876 pSet = new SfxItemSet( *pItemSet ); 2877 } 2878 2879 SwRedlineExtraData_FmtColl::~SwRedlineExtraData_FmtColl() 2880 { 2881 delete pSet; 2882 } 2883 2884 SwRedlineExtraData* SwRedlineExtraData_FmtColl::CreateNew() const 2885 { 2886 return new SwRedlineExtraData_FmtColl( sFmtNm, nPoolId, pSet ); 2887 } 2888 2889 void SwRedlineExtraData_FmtColl::Reject( SwPaM& rPam ) const 2890 { 2891 SwDoc* pDoc = rPam.GetDoc(); 2892 2893 // was ist mit Undo ? ist das abgeschaltet ?? 2894 SwTxtFmtColl* pColl = USHRT_MAX == nPoolId 2895 ? pDoc->FindTxtFmtCollByName( sFmtNm ) 2896 : pDoc->GetTxtCollFromPool( nPoolId ); 2897 if( pColl ) 2898 pDoc->SetTxtFmtColl( rPam, pColl, false ); 2899 2900 if( pSet ) 2901 { 2902 rPam.SetMark(); 2903 SwPosition& rMark = *rPam.GetMark(); 2904 SwTxtNode* pTNd = rMark.nNode.GetNode().GetTxtNode(); 2905 if( pTNd ) 2906 { 2907 rMark.nContent.Assign( pTNd, pTNd->GetTxt().Len() ); 2908 2909 if( pTNd->HasSwAttrSet() ) 2910 { 2911 // nur die setzen, die nicht mehr vorhanden sind. Andere 2912 // koennen jetzt veraendert drin stehen, aber die werden 2913 // nicht angefasst. 2914 SfxItemSet aTmp( *pSet ); 2915 aTmp.Differentiate( *pTNd->GetpSwAttrSet() ); 2916 pDoc->InsertItemSet( rPam, aTmp, 0 ); 2917 } 2918 else 2919 { 2920 pDoc->InsertItemSet( rPam, *pSet, 0 ); 2921 } 2922 } 2923 rPam.DeleteMark(); 2924 } 2925 } 2926 2927 int SwRedlineExtraData_FmtColl::operator == ( const SwRedlineExtraData& r) const 2928 { 2929 const SwRedlineExtraData_FmtColl& rCmp = (SwRedlineExtraData_FmtColl&)r; 2930 return sFmtNm == rCmp.sFmtNm && nPoolId == rCmp.nPoolId && 2931 ( ( !pSet && !rCmp.pSet ) || 2932 ( pSet && rCmp.pSet && *pSet == *rCmp.pSet ) ); 2933 } 2934 2935 void SwRedlineExtraData_FmtColl::SetItemSet( const SfxItemSet& rSet ) 2936 { 2937 delete pSet; 2938 if( rSet.Count() ) 2939 pSet = new SfxItemSet( rSet ); 2940 else 2941 pSet = 0; 2942 } 2943 2944 2945 SwRedlineExtraData_Format::SwRedlineExtraData_Format( const SfxItemSet& rSet ) 2946 { 2947 SfxItemIter aIter( rSet ); 2948 const SfxPoolItem* pItem = aIter.FirstItem(); 2949 while( sal_True ) 2950 { 2951 aWhichIds.Insert( pItem->Which(), aWhichIds.Count() ); 2952 if( aIter.IsAtEnd() ) 2953 break; 2954 pItem = aIter.NextItem(); 2955 } 2956 } 2957 2958 SwRedlineExtraData_Format::SwRedlineExtraData_Format( 2959 const SwRedlineExtraData_Format& rCpy ) 2960 : SwRedlineExtraData(), aWhichIds( (sal_uInt8)rCpy.aWhichIds.Count() ) 2961 { 2962 aWhichIds.Insert( &rCpy.aWhichIds, 0 ); 2963 } 2964 2965 SwRedlineExtraData_Format::~SwRedlineExtraData_Format() 2966 { 2967 } 2968 2969 SwRedlineExtraData* SwRedlineExtraData_Format::CreateNew() const 2970 { 2971 return new SwRedlineExtraData_Format( *this ); 2972 } 2973 2974 void SwRedlineExtraData_Format::Reject( SwPaM& rPam ) const 2975 { 2976 SwDoc* pDoc = rPam.GetDoc(); 2977 2978 RedlineMode_t eOld = pDoc->GetRedlineMode(); 2979 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE))); 2980 2981 // eigentlich muesste hier das Attribut zurueck gesetzt werden!!! 2982 for( sal_uInt16 n = 0, nEnd = aWhichIds.Count(); n < nEnd; ++n ) 2983 { 2984 pDoc->InsertPoolItem( 2985 rPam, *GetDfltAttr( aWhichIds[ n ] ), nsSetAttrMode::SETATTR_DONTEXPAND ); 2986 } 2987 2988 pDoc->SetRedlineMode_intern( eOld ); 2989 } 2990 2991 int SwRedlineExtraData_Format::operator == ( const SwRedlineExtraData& rCmp ) const 2992 { 2993 int nRet = 1; 2994 sal_uInt16 n = 0, nEnd = aWhichIds.Count(); 2995 if( nEnd != ((SwRedlineExtraData_Format&)rCmp).aWhichIds.Count() ) 2996 nRet = 0; 2997 else 2998 for( ; n < nEnd; ++n ) 2999 if( ((SwRedlineExtraData_Format&)rCmp).aWhichIds[n] != aWhichIds[n]) 3000 { 3001 nRet = 0; 3002 break; 3003 } 3004 return nRet; 3005 } 3006 3007 /* */ 3008 3009 SwRedlineData::SwRedlineData( RedlineType_t eT, sal_uInt16 nAut ) 3010 : pNext( 0 ), pExtraData( 0 ), eType( eT ), nAuthor( nAut ), nSeqNo( 0 ) 3011 { 3012 aStamp.SetSec( 0 ); 3013 aStamp.Set100Sec( 0 ); 3014 } 3015 3016 SwRedlineData::SwRedlineData( 3017 const SwRedlineData& rCpy, 3018 sal_Bool bCpyNext ) 3019 : pNext( ( bCpyNext && rCpy.pNext ) ? new SwRedlineData( *rCpy.pNext ) : 0 ) 3020 , pExtraData( rCpy.pExtraData ? rCpy.pExtraData->CreateNew() : 0 ) 3021 , sComment( rCpy.sComment ) 3022 , aStamp( rCpy.aStamp ) 3023 , eType( rCpy.eType ) 3024 , nAuthor( rCpy.nAuthor ) 3025 , 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