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( rPam, *GetDfltAttr( aWhichIds[ n ] ), 2985 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( const SwRedlineData& rCpy, sal_Bool bCpyNext ) 3017 : 3018 pNext( (bCpyNext && rCpy.pNext) ? new SwRedlineData( *rCpy.pNext ) : 0 ), 3019 pExtraData( rCpy.pExtraData ? rCpy.pExtraData->CreateNew() : 0 ), 3020 sComment( rCpy.sComment ), aStamp( rCpy.aStamp ), eType( rCpy.eType ), 3021 nAuthor( rCpy.nAuthor ), nSeqNo( rCpy.nSeqNo ) 3022 { 3023 } 3024 3025 // fuer sw3io: pNext geht in eigenen Besitz ueber! 3026 SwRedlineData::SwRedlineData(RedlineType_t eT, sal_uInt16 nAut, const DateTime& rDT, 3027 const String& rCmnt, SwRedlineData *pNxt, SwRedlineExtraData* pData) 3028 : pNext(pNxt), pExtraData(pData), sComment(rCmnt), aStamp(rDT), 3029 eType(eT), nAuthor(nAut), nSeqNo(0) 3030 { 3031 } 3032 3033 SwRedlineData::~SwRedlineData() 3034 { 3035 delete pExtraData; 3036 delete pNext; 3037 } 3038 3039 // ExtraData wird kopiert, der Pointer geht also NICHT in den Besitz 3040 // des RedlineObjectes! 3041 void SwRedlineData::SetExtraData( const SwRedlineExtraData* pData ) 3042 { 3043 delete pExtraData; 3044 3045 if( pData ) 3046 pExtraData = pData->CreateNew(); 3047 else 3048 pExtraData = 0; 3049 } 3050 3051 // #111827# 3052 String SwRedlineData::GetDescr() const 3053 { 3054 String aResult; 3055 3056 aResult += String(SW_RES(STR_REDLINE_INSERT + GetType())); 3057 3058 return aResult; 3059 } 3060 3061 /* */ 3062 3063 SwRedline::SwRedline(RedlineType_t eTyp, const SwPaM& rPam ) 3064 : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ), 3065 pRedlineData( new SwRedlineData( eTyp, GetDoc()->GetRedlineAuthor() ) ), 3066 pCntntSect( 0 ) 3067 { 3068 bDelLastPara = bIsLastParaDelete = sal_False; 3069 bIsVisible = sal_True; 3070 if( !rPam.HasMark() ) 3071 DeleteMark(); 3072 } 3073 3074 SwRedline::SwRedline( const SwRedlineData& rData, const SwPaM& rPam ) 3075 : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ), 3076 pRedlineData( new SwRedlineData( rData )), 3077 pCntntSect( 0 ) 3078 { 3079 bDelLastPara = bIsLastParaDelete = sal_False; 3080 bIsVisible = sal_True; 3081 if( !rPam.HasMark() ) 3082 DeleteMark(); 3083 } 3084 3085 SwRedline::SwRedline( const SwRedlineData& rData, const SwPosition& rPos ) 3086 : SwPaM( rPos ), 3087 pRedlineData( new SwRedlineData( rData )), 3088 pCntntSect( 0 ) 3089 { 3090 bDelLastPara = bIsLastParaDelete = sal_False; 3091 bIsVisible = sal_True; 3092 } 3093 3094 SwRedline::SwRedline( const SwRedline& rCpy ) 3095 : SwPaM( *rCpy.GetMark(), *rCpy.GetPoint() ), 3096 pRedlineData( new SwRedlineData( *rCpy.pRedlineData )), 3097 pCntntSect( 0 ) 3098 { 3099 bDelLastPara = bIsLastParaDelete = sal_False; 3100 bIsVisible = sal_True; 3101 if( !rCpy.HasMark() ) 3102 DeleteMark(); 3103 } 3104 3105 SwRedline::~SwRedline() 3106 { 3107 if( pCntntSect ) 3108 { 3109 // dann den Content Bereich loeschen 3110 if( !GetDoc()->IsInDtor() ) 3111 GetDoc()->DeleteSection( &pCntntSect->GetNode() ); 3112 delete pCntntSect; 3113 } 3114 delete pRedlineData; 3115 } 3116 3117 // liegt eine gueltige Selektion vor? 3118 sal_Bool SwRedline::HasValidRange() const 3119 { 3120 const SwNode* pPtNd = &GetPoint()->nNode.GetNode(), 3121 * pMkNd = &GetMark()->nNode.GetNode(); 3122 if( pPtNd->StartOfSectionNode() == pMkNd->StartOfSectionNode() && 3123 !pPtNd->StartOfSectionNode()->IsTableNode() && 3124 // JP 18.5.2001: Bug 87222 - invalid if points on the end of content 3125 // DVO 25.03.2002: #96530# end-of-content only invalid if no content 3126 // index exists 3127 ( pPtNd != pMkNd || GetContentIdx() != NULL || 3128 pPtNd != &pPtNd->GetNodes().GetEndOfContent() ) 3129 ) 3130 return sal_True; 3131 return sal_False; 3132 } 3133 3134 void SwRedline::CallDisplayFunc( sal_uInt16 nLoop ) 3135 { 3136 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() ) 3137 { 3138 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE: 3139 Show( nLoop ); 3140 break; 3141 case nsRedlineMode_t::REDLINE_SHOW_INSERT: 3142 Hide( nLoop ); 3143 break; 3144 case nsRedlineMode_t::REDLINE_SHOW_DELETE: 3145 ShowOriginal( nLoop ); 3146 break; 3147 } 3148 } 3149 3150 void SwRedline::Show( sal_uInt16 nLoop ) 3151 { 3152 if( 1 <= nLoop ) 3153 { 3154 SwDoc* pDoc = GetDoc(); 3155 RedlineMode_t eOld = pDoc->GetRedlineMode(); 3156 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE)); 3157 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 3158 3159 switch( GetType() ) 3160 { 3161 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt 3162 bIsVisible = sal_True; 3163 MoveFromSection(); 3164 break; 3165 3166 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht 3167 bIsVisible = sal_True; 3168 MoveFromSection(); 3169 break; 3170 3171 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet 3172 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert 3173 InvalidateRange(); 3174 break; 3175 default: 3176 break; 3177 } 3178 pDoc->SetRedlineMode_intern( eOld ); 3179 } 3180 } 3181 3182 void SwRedline::Hide( sal_uInt16 nLoop ) 3183 { 3184 SwDoc* pDoc = GetDoc(); 3185 RedlineMode_t eOld = pDoc->GetRedlineMode(); 3186 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE)); 3187 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 3188 3189 switch( GetType() ) 3190 { 3191 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt 3192 bIsVisible = sal_True; 3193 if( 1 <= nLoop ) 3194 MoveFromSection(); 3195 break; 3196 3197 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht 3198 bIsVisible = sal_False; 3199 switch( nLoop ) 3200 { 3201 case 0: MoveToSection(); break; 3202 case 1: CopyToSection(); break; 3203 case 2: DelCopyOfSection(); break; 3204 } 3205 break; 3206 3207 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet 3208 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert 3209 if( 1 <= nLoop ) 3210 InvalidateRange(); 3211 break; 3212 default: 3213 break; 3214 } 3215 pDoc->SetRedlineMode_intern( eOld ); 3216 } 3217 3218 void SwRedline::ShowOriginal( sal_uInt16 nLoop ) 3219 { 3220 SwDoc* pDoc = GetDoc(); 3221 RedlineMode_t eOld = pDoc->GetRedlineMode(); 3222 SwRedlineData* pCur; 3223 3224 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE)); 3225 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 3226 3227 // bestimme den Type, ist der erste auf Stack 3228 for( pCur = pRedlineData; pCur->pNext; ) 3229 pCur = pCur->pNext; 3230 3231 switch( pCur->eType ) 3232 { 3233 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt 3234 bIsVisible = sal_False; 3235 switch( nLoop ) 3236 { 3237 case 0: MoveToSection(); break; 3238 case 1: CopyToSection(); break; 3239 case 2: DelCopyOfSection(); break; 3240 } 3241 break; 3242 3243 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht 3244 bIsVisible = sal_True; 3245 if( 1 <= nLoop ) 3246 MoveFromSection(); 3247 break; 3248 3249 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet 3250 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert 3251 if( 1 <= nLoop ) 3252 InvalidateRange(); 3253 break; 3254 default: 3255 break; 3256 } 3257 pDoc->SetRedlineMode_intern( eOld ); 3258 } 3259 3260 3261 void SwRedline::InvalidateRange() // das Layout anstossen 3262 { 3263 sal_uLong nSttNd = GetMark()->nNode.GetIndex(), 3264 nEndNd = GetPoint()->nNode.GetIndex(); 3265 sal_uInt16 nSttCnt = GetMark()->nContent.GetIndex(), 3266 nEndCnt = GetPoint()->nContent.GetIndex(); 3267 3268 if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt )) 3269 { 3270 sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp; 3271 nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (sal_uInt16)nTmp; 3272 } 3273 3274 SwUpdateAttr aHt( 0, 0, RES_FMT_CHG ); 3275 SwNodes& rNds = GetDoc()->GetNodes(); 3276 SwNode* pNd; 3277 for( sal_uLong n = nSttNd; n <= nEndNd; ++n ) 3278 if( ND_TEXTNODE == ( pNd = rNds[ n ] )->GetNodeType() ) 3279 { 3280 aHt.nStart = n == nSttNd ? nSttCnt : 0; 3281 aHt.nEnd = n == nEndNd ? nEndCnt : ((SwTxtNode*)pNd)->GetTxt().Len(); 3282 ((SwTxtNode*)pNd)->ModifyNotification( &aHt, &aHt ); 3283 } 3284 } 3285 3286 /************************************************************************* 3287 * SwRedline::CalcStartEnd() 3288 * Calculates the start and end position of the intersection rTmp and 3289 * text node nNdIdx 3290 *************************************************************************/ 3291 3292 void SwRedline::CalcStartEnd( sal_uLong nNdIdx, sal_uInt16& nStart, sal_uInt16& nEnd ) const 3293 { 3294 const SwPosition *pRStt = Start(), *pREnd = End(); 3295 if( pRStt->nNode < nNdIdx ) 3296 { 3297 if( pREnd->nNode > nNdIdx ) 3298 { 3299 nStart = 0; // Absatz ist komplett enthalten 3300 nEnd = STRING_LEN; 3301 } 3302 else 3303 { 3304 ASSERT( pREnd->nNode == nNdIdx, 3305 "SwRedlineItr::Seek: GetRedlinePos Error" ); 3306 nStart = 0; // Absatz wird vorne ueberlappt 3307 nEnd = pREnd->nContent.GetIndex(); 3308 } 3309 } 3310 else if( pRStt->nNode == nNdIdx ) 3311 { 3312 nStart = pRStt->nContent.GetIndex(); 3313 if( pREnd->nNode == nNdIdx ) 3314 nEnd = pREnd->nContent.GetIndex(); // Innerhalb des Absatzes 3315 else 3316 nEnd = STRING_LEN; // Absatz wird hinten ueberlappt 3317 } 3318 else 3319 { 3320 nStart = STRING_LEN; 3321 nEnd = STRING_LEN; 3322 } 3323 } 3324 3325 void SwRedline::MoveToSection() 3326 { 3327 if( !pCntntSect ) 3328 { 3329 const SwPosition* pStt = Start(), 3330 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint(); 3331 3332 SwDoc* pDoc = GetDoc(); 3333 SwPaM aPam( *pStt, *pEnd ); 3334 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode(); 3335 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode(); 3336 3337 if( !pCSttNd ) 3338 { 3339 // damit die Indizies der anderen Redlines nicht mitverschoben 3340 // werden, diese aufs Ende setzen (ist exclusive). 3341 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 3342 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 3343 { 3344 SwRedline* pRedl = rTbl[ n ]; 3345 if( pRedl->GetBound(sal_True) == *pStt ) 3346 pRedl->GetBound(sal_True) = *pEnd; 3347 if( pRedl->GetBound(sal_False) == *pStt ) 3348 pRedl->GetBound(sal_False) = *pEnd; 3349 } 3350 } 3351 3352 SwStartNode* pSttNd; 3353 SwNodes& rNds = pDoc->GetNodes(); 3354 if( pCSttNd || pCEndNd ) 3355 { 3356 SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() ) 3357 ? ((SwTxtNode*)pCSttNd)->GetTxtColl() 3358 : (pCEndNd && pCEndNd->IsTxtNode() ) 3359 ? ((SwTxtNode*)pCEndNd)->GetTxtColl() 3360 : pDoc->GetTxtCollFromPool( 3361 RES_POOLCOLL_STANDARD ); 3362 3363 pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ), 3364 SwNormalStartNode, pColl ); 3365 SwTxtNode* pTxtNd = rNds[ pSttNd->GetIndex() + 1 ]->GetTxtNode(); 3366 3367 SwNodeIndex aNdIdx( *pTxtNd ); 3368 SwPosition aPos( aNdIdx, SwIndex( pTxtNd )); 3369 if( pCSttNd && pCEndNd ) 3370 pDoc->MoveAndJoin( aPam, aPos, IDocumentContentOperations::DOC_MOVEDEFAULT ); 3371 else 3372 { 3373 if( pCSttNd && !pCEndNd ) 3374 bDelLastPara = sal_True; 3375 pDoc->MoveRange( aPam, aPos, 3376 IDocumentContentOperations::DOC_MOVEDEFAULT ); 3377 } 3378 } 3379 else 3380 { 3381 pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ), 3382 SwNormalStartNode ); 3383 3384 SwPosition aPos( *pSttNd->EndOfSectionNode() ); 3385 pDoc->MoveRange( aPam, aPos, 3386 IDocumentContentOperations::DOC_MOVEDEFAULT ); 3387 } 3388 pCntntSect = new SwNodeIndex( *pSttNd ); 3389 3390 if( pStt == GetPoint() ) 3391 Exchange(); 3392 3393 DeleteMark(); 3394 } 3395 else 3396 InvalidateRange(); 3397 } 3398 3399 void SwRedline::CopyToSection() 3400 { 3401 if( !pCntntSect ) 3402 { 3403 const SwPosition* pStt = Start(), 3404 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint(); 3405 3406 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode(); 3407 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode(); 3408 3409 SwStartNode* pSttNd; 3410 SwDoc* pDoc = GetDoc(); 3411 SwNodes& rNds = pDoc->GetNodes(); 3412 3413 sal_Bool bSaveCopyFlag = pDoc->IsCopyIsMove(), 3414 bSaveRdlMoveFlg = pDoc->IsRedlineMove(); 3415 pDoc->SetCopyIsMove( sal_True ); 3416 3417 // #100619# The IsRedlineMove() flag causes the behaviour of the 3418 // SwDoc::_CopyFlyInFly method to change, which will eventually be 3419 // called by the pDoc->Copy line below (through SwDoc::_Copy, 3420 // SwDoc::CopyWithFlyInFly). This rather obscure bugfix was introduced 3421 // for #63198# and #64896#, and apparently never really worked. 3422 pDoc->SetRedlineMove( pStt->nContent == 0 ); 3423 3424 if( pCSttNd ) 3425 { 3426 SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() ) 3427 ? ((SwTxtNode*)pCSttNd)->GetTxtColl() 3428 : pDoc->GetTxtCollFromPool( 3429 RES_POOLCOLL_STANDARD ); 3430 3431 pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ), 3432 SwNormalStartNode, pColl ); 3433 3434 SwNodeIndex aNdIdx( *pSttNd, 1 ); 3435 SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode(); 3436 SwPosition aPos( aNdIdx, SwIndex( pTxtNd )); 3437 pDoc->CopyRange( *this, aPos, false ); 3438 3439 // JP 08.10.98: die Vorlage vom EndNode ggfs. mit uebernehmen 3440 // - ist im Doc::Copy nicht erwuenscht 3441 if( pCEndNd && pCEndNd != pCSttNd ) 3442 { 3443 SwCntntNode* pDestNd = aPos.nNode.GetNode().GetCntntNode(); 3444 if( pDestNd ) 3445 { 3446 if( pDestNd->IsTxtNode() && pCEndNd->IsTxtNode() ) 3447 ((SwTxtNode*)pCEndNd)->CopyCollFmt( 3448 *(SwTxtNode*)pDestNd ); 3449 else 3450 pDestNd->ChgFmtColl( pCEndNd->GetFmtColl() ); 3451 } 3452 } 3453 } 3454 else 3455 { 3456 pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ), 3457 SwNormalStartNode ); 3458 3459 if( pCEndNd ) 3460 { 3461 SwPosition aPos( *pSttNd->EndOfSectionNode() ); 3462 pDoc->CopyRange( *this, aPos, false ); 3463 } 3464 else 3465 { 3466 SwNodeIndex aInsPos( *pSttNd->EndOfSectionNode() ); 3467 SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 ); 3468 pDoc->CopyWithFlyInFly( aRg, 0, aInsPos ); 3469 } 3470 } 3471 pCntntSect = new SwNodeIndex( *pSttNd ); 3472 3473 pDoc->SetCopyIsMove( bSaveCopyFlag ); 3474 pDoc->SetRedlineMove( bSaveRdlMoveFlg ); 3475 } 3476 } 3477 3478 void SwRedline::DelCopyOfSection() 3479 { 3480 if( pCntntSect ) 3481 { 3482 const SwPosition* pStt = Start(), 3483 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint(); 3484 3485 SwDoc* pDoc = GetDoc(); 3486 SwPaM aPam( *pStt, *pEnd ); 3487 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode(); 3488 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode(); 3489 3490 if( !pCSttNd ) 3491 { 3492 // damit die Indizies der anderen Redlines nicht mitverschoben 3493 // werden, diese aufs Ende setzen (ist exclusive). 3494 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 3495 for( sal_uInt16 n = 0; n < rTbl.Count(); ++n ) 3496 { 3497 SwRedline* pRedl = rTbl[ n ]; 3498 if( pRedl->GetBound(sal_True) == *pStt ) 3499 pRedl->GetBound(sal_True) = *pEnd; 3500 if( pRedl->GetBound(sal_False) == *pStt ) 3501 pRedl->GetBound(sal_False) = *pEnd; 3502 } 3503 } 3504 3505 if( pCSttNd && pCEndNd ) 3506 { 3507 // --> OD 2009-08-20 #i100466# 3508 // force a <join next> on <delete and join> operation 3509 pDoc->DeleteAndJoin( aPam, true ); 3510 // <-- 3511 } 3512 else if( pCSttNd || pCEndNd ) 3513 { 3514 if( pCSttNd && !pCEndNd ) 3515 bDelLastPara = sal_True; 3516 pDoc->DeleteRange( aPam ); 3517 3518 if( bDelLastPara ) 3519 { 3520 // #100611# To prevent dangling references to the paragraph to 3521 // be deleted, redline that point into this paragraph should be 3522 // moved to the new end position. Since redlines in the redline 3523 // table are sorted and the pEnd position is an endnode (see 3524 // bDelLastPara condition above), only redlines before the 3525 // current ones can be affected. 3526 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 3527 sal_uInt16 n = rTbl.GetPos( this ); 3528 ASSERT( n != USHRT_MAX, "How strange. We don't exist!" ); 3529 for( sal_Bool bBreak = sal_False; !bBreak && n > 0; ) 3530 { 3531 --n; 3532 bBreak = sal_True; 3533 if( rTbl[ n ]->GetBound(sal_True) == *aPam.GetPoint() ) 3534 { 3535 rTbl[ n ]->GetBound(sal_True) = *pEnd; 3536 bBreak = sal_False; 3537 } 3538 if( rTbl[ n ]->GetBound(sal_False) == *aPam.GetPoint() ) 3539 { 3540 rTbl[ n ]->GetBound(sal_False) = *pEnd; 3541 bBreak = sal_False; 3542 } 3543 } 3544 3545 SwPosition aEnd( *pEnd ); 3546 *GetPoint() = *pEnd; 3547 *GetMark() = *pEnd; 3548 DeleteMark(); 3549 3550 aPam.GetBound( sal_True ).nContent.Assign( 0, 0 ); 3551 aPam.GetBound( sal_False ).nContent.Assign( 0, 0 ); 3552 aPam.DeleteMark(); 3553 pDoc->DelFullPara( aPam ); 3554 } 3555 } 3556 else 3557 { 3558 pDoc->DeleteRange( aPam ); 3559 } 3560 3561 if( pStt == GetPoint() ) 3562 Exchange(); 3563 3564 DeleteMark(); 3565 } 3566 } 3567 3568 void SwRedline::MoveFromSection() 3569 { 3570 if( pCntntSect ) 3571 { 3572 SwDoc* pDoc = GetDoc(); 3573 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl(); 3574 SvPtrarr aBeforeArr( 16, 16 ), aBehindArr( 16, 16 ); 3575 sal_uInt16 nMyPos = rTbl.GetPos( this ); 3576 ASSERT( this, "this nicht im Array?" ); 3577 sal_Bool bBreak = sal_False; 3578 sal_uInt16 n; 3579 3580 for( n = nMyPos+1; !bBreak && n < rTbl.Count(); ++n ) 3581 { 3582 bBreak = sal_True; 3583 if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() ) 3584 { 3585 void* pTmp = &rTbl[ n ]->GetBound(sal_True); 3586 aBehindArr.Insert( pTmp, aBehindArr.Count()); 3587 bBreak = sal_False; 3588 } 3589 if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() ) 3590 { 3591 void* pTmp = &rTbl[ n ]->GetBound(sal_False); 3592 aBehindArr.Insert( pTmp, aBehindArr.Count() ); 3593 bBreak = sal_False; 3594 } 3595 } 3596 for( bBreak = sal_False, n = nMyPos; !bBreak && n ; ) 3597 { 3598 --n; 3599 bBreak = sal_True; 3600 if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() ) 3601 { 3602 void* pTmp = &rTbl[ n ]->GetBound(sal_True); 3603 aBeforeArr.Insert( pTmp, aBeforeArr.Count() ); 3604 bBreak = sal_False; 3605 } 3606 if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() ) 3607 { 3608 void* pTmp = &rTbl[ n ]->GetBound(sal_False); 3609 aBeforeArr.Insert( pTmp, aBeforeArr.Count() ); 3610 bBreak = sal_False; 3611 } 3612 } 3613 3614 // --> OD 2009-03-17 #i95711# 3615 const SwNode* pKeptCntntSectNode( &pCntntSect->GetNode() ); 3616 // <-- 3617 { 3618 SwPaM aPam( pCntntSect->GetNode(), 3619 *pCntntSect->GetNode().EndOfSectionNode(), 1, 3620 ( bDelLastPara ? -2 : -1 ) ); 3621 SwCntntNode* pCNd = aPam.GetCntntNode(); 3622 if( pCNd ) 3623 aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() ); 3624 else 3625 aPam.GetPoint()->nNode++; 3626 3627 SwFmtColl* pColl = pCNd && pCNd->Len() && aPam.GetPoint()->nNode != 3628 aPam.GetMark()->nNode 3629 ? pCNd->GetFmtColl() : 0; 3630 3631 SwNodeIndex aNdIdx( GetPoint()->nNode, -1 ); 3632 sal_uInt16 nPos = GetPoint()->nContent.GetIndex(); 3633 3634 SwPosition aPos( *GetPoint() ); 3635 if( bDelLastPara && *aPam.GetPoint() == *aPam.GetMark() ) 3636 { 3637 aPos.nNode--; 3638 3639 pDoc->AppendTxtNode( aPos ); 3640 } 3641 else 3642 { 3643 pDoc->MoveRange( aPam, aPos, 3644 IDocumentContentOperations::DOC_MOVEALLFLYS ); 3645 } 3646 3647 SetMark(); 3648 *GetPoint() = aPos; 3649 GetMark()->nNode = aNdIdx.GetIndex() + 1; 3650 pCNd = GetMark()->nNode.GetNode().GetCntntNode(); 3651 GetMark()->nContent.Assign( pCNd, nPos ); 3652 3653 if( bDelLastPara ) 3654 { 3655 GetPoint()->nNode++; 3656 GetPoint()->nContent.Assign( pCNd = GetCntntNode(), 0 ); 3657 bDelLastPara = sal_False; 3658 } 3659 else if( pColl ) 3660 pCNd = GetCntntNode(); 3661 3662 if( pColl && pCNd ) 3663 pCNd->ChgFmtColl( pColl ); 3664 } 3665 // --> OD 2009-03-17 #i95771# 3666 // Under certain conditions the previous <SwDoc::Move(..)> has already 3667 // remove the change tracking section of this <SwRedline> instance from 3668 // the change tracking nodes area. 3669 // Thus, check, if <pCntntSect> still points to the change tracking section 3670 // by comparing it with the "indexed" <SwNode> instance copied before 3671 // perform the intrinsic move. 3672 // Note: Such condition is e.g. a "delete" change tracking only containing a table. 3673 if ( &pCntntSect->GetNode() == pKeptCntntSectNode ) 3674 { 3675 pDoc->DeleteSection( &pCntntSect->GetNode() ); 3676 } 3677 // <-- 3678 delete pCntntSect, pCntntSect = 0; 3679 3680 // #100611# adjustment of redline table positions must take start and 3681 // end into account, not point and mark. 3682 for( n = 0; n < aBeforeArr.Count(); ++n ) 3683 *(SwPosition*)aBeforeArr[ n ] = *Start(); 3684 for( n = 0; n < aBehindArr.Count(); ++n ) 3685 *(SwPosition*)aBehindArr[ n ] = *End(); 3686 } 3687 else 3688 InvalidateRange(); 3689 } 3690 3691 // fuers Undo 3692 void SwRedline::SetContentIdx( const SwNodeIndex* pIdx ) 3693 { 3694 if( pIdx && !pCntntSect ) 3695 { 3696 pCntntSect = new SwNodeIndex( *pIdx ); 3697 bIsVisible = sal_False; 3698 } 3699 else if( !pIdx && pCntntSect ) 3700 { 3701 delete pCntntSect, pCntntSect = 0; 3702 bIsVisible = sal_False; 3703 } 3704 #ifdef DBG_UTIL 3705 else 3706 ASSERT( !this, "das ist keine gueltige Operation" ); 3707 #endif 3708 } 3709 3710 sal_Bool SwRedline::CanCombine( const SwRedline& rRedl ) const 3711 { 3712 return IsVisible() && rRedl.IsVisible() && 3713 pRedlineData->CanCombine( *rRedl.pRedlineData ); 3714 } 3715 3716 void SwRedline::PushData( const SwRedline& rRedl, sal_Bool bOwnAsNext ) 3717 { 3718 // SwRedlineData* pNew = new SwRedlineData( rRedl.GetType(), 3719 // rRedl.GetAuthor() ); 3720 SwRedlineData* pNew = new SwRedlineData( *rRedl.pRedlineData, sal_False ); 3721 if( bOwnAsNext ) 3722 { 3723 pNew->pNext = pRedlineData; 3724 pRedlineData = pNew; 3725 } 3726 else 3727 { 3728 pNew->pNext = pRedlineData->pNext; 3729 pRedlineData->pNext = pNew; 3730 } 3731 } 3732 3733 sal_Bool SwRedline::PopData() 3734 { 3735 if( !pRedlineData->pNext ) 3736 return sal_False; 3737 SwRedlineData* pCur = pRedlineData; 3738 pRedlineData = pCur->pNext; 3739 pCur->pNext = 0; 3740 delete pCur; 3741 return sal_True; 3742 } 3743 3744 sal_uInt16 SwRedline::GetStackCount() const 3745 { 3746 sal_uInt16 nRet = 1; 3747 for( SwRedlineData* pCur = pRedlineData; pCur->pNext; ++nRet ) 3748 pCur = pCur->pNext; 3749 return nRet; 3750 } 3751 3752 // -> #111827# 3753 sal_uInt16 SwRedline::GetAuthor( sal_uInt16 nPos ) const 3754 { 3755 return GetRedlineData(nPos).nAuthor; 3756 } 3757 3758 const String& SwRedline::GetAuthorString( sal_uInt16 nPos ) const 3759 { 3760 return SW_MOD()->GetRedlineAuthor(GetRedlineData(nPos).nAuthor); 3761 } 3762 3763 const DateTime& SwRedline::GetTimeStamp( sal_uInt16 nPos ) const 3764 { 3765 return GetRedlineData(nPos).aStamp; 3766 } 3767 3768 RedlineType_t SwRedline::GetRealType( sal_uInt16 nPos ) const 3769 { 3770 return GetRedlineData(nPos).eType; 3771 } 3772 3773 const String& SwRedline::GetComment( sal_uInt16 nPos ) const 3774 { 3775 return GetRedlineData(nPos).sComment; 3776 } 3777 // <- #111827# 3778 3779 int SwRedline::operator==( const SwRedline& rCmp ) const 3780 { 3781 return this == &rCmp; 3782 } 3783 3784 int SwRedline::operator<( const SwRedline& rCmp ) const 3785 { 3786 sal_Bool nResult = sal_False; 3787 3788 if (*Start() < *rCmp.Start()) 3789 nResult = sal_True; 3790 else if (*Start() == *rCmp.Start()) 3791 if (*End() < *rCmp.End()) 3792 nResult = sal_True; 3793 3794 return nResult; 3795 } 3796 3797 // -> #111827# 3798 const SwRedlineData & SwRedline::GetRedlineData(sal_uInt16 nPos) const 3799 { 3800 SwRedlineData * pCur = pRedlineData; 3801 3802 while (nPos > 0 && NULL != pCur->pNext) 3803 { 3804 pCur = pCur->pNext; 3805 3806 nPos--; 3807 } 3808 3809 ASSERT( 0 == nPos, "Pos angabe ist zu gross" ); 3810 3811 return *pCur; 3812 } 3813 3814 String SwRedline::GetDescr(sal_uInt16 nPos) 3815 { 3816 String aResult; 3817 3818 // get description of redline data (e.g.: "insert $1") 3819 aResult = GetRedlineData(nPos).GetDescr(); 3820 3821 SwPaM * pPaM = NULL; 3822 bool bDeletePaM = false; 3823 3824 // if this redline is visible the content is in this PaM 3825 if (NULL == pCntntSect) 3826 { 3827 pPaM = this; 3828 } 3829 else // otherwise it is saved in pCntntSect 3830 { 3831 SwNodeIndex aTmpIdx( *pCntntSect->GetNode().EndOfSectionNode() ); 3832 pPaM = new SwPaM(*pCntntSect, aTmpIdx ); 3833 bDeletePaM = true; 3834 } 3835 3836 // replace $1 in description by description of the redlines text 3837 String aTmpStr; 3838 aTmpStr += String(SW_RES(STR_START_QUOTE)); 3839 aTmpStr += ShortenString(pPaM->GetTxt(), nUndoStringLength, 3840 String(SW_RES(STR_LDOTS))); 3841 aTmpStr += String(SW_RES(STR_END_QUOTE)); 3842 3843 SwRewriter aRewriter; 3844 aRewriter.AddRule(UNDO_ARG1, aTmpStr); 3845 3846 aResult = aRewriter.Apply(aResult); 3847 3848 if (bDeletePaM) 3849 delete pPaM; 3850 3851 return aResult; 3852 } 3853 // <- #111827# 3854 3855 3856 bool SwDoc::IsInRedlines(const SwNode & rNode) const 3857 { 3858 SwPosition aPos(rNode); 3859 SwNode & rEndOfRedlines = GetNodes().GetEndOfRedlines(); 3860 SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()), 3861 SwPosition(rEndOfRedlines)); 3862 3863 return aPam.ContainsPosition(aPos) ? true : false; 3864 } 3865