merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / doc / docredln.cxx
blobec6e88f9944b4ab0afd7cce076b7281a502204c6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docredln.cxx,v $
10 * $Revision: 1.51.122.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <tools/shl.hxx>
37 #ifndef _SFX_ITEMITER_HXX //autogen
38 #include <svtools/itemiter.hxx>
39 #endif
40 #include <sfx2/app.hxx>
41 #include <svx/colritem.hxx>
42 #include <svx/udlnitem.hxx>
43 #include <svx/crsditem.hxx>
44 #include <swmodule.hxx>
45 #include <doc.hxx>
46 #include <docary.hxx>
47 #include <ndtxt.hxx>
48 #include <redline.hxx>
49 #include <swundo.hxx>
50 #include <undobj.hxx>
51 #include <pamtyp.hxx>
52 #include <poolfmt.hxx>
53 #include <viewsh.hxx>
54 #include <rootfrm.hxx>
56 #include <comcore.hrc>
58 using namespace com::sun::star;
60 TYPEINIT1(SwRedlineHint, SfxHint);
62 #ifdef PRODUCT
64 #define _CHECK_REDLINE( pDoc )
65 #define _DEBUG_REDLINE( pDoc )
67 #else
69 #define _ERROR_PREFIX "redline table corrupted: "
71 // helper function for lcl_CheckRedline
72 // 1. make sure that pPos->nContent points into pPos->nNode
73 // (or into the 'special' no-content-node-IndexReg)
74 // 2. check that position is valid and doesn't point behind text
75 void lcl_CheckPosition( const SwPosition* pPos )
77 SwPosition aComparePos( *pPos );
78 aComparePos.nContent.Assign(
79 aComparePos.nNode.GetNode().GetCntntNode(), 0 );
80 DBG_ASSERT( pPos->nContent.GetIdxReg() ==
81 aComparePos.nContent.GetIdxReg(),
82 _ERROR_PREFIX "illegal position" );
84 SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
85 if( pTxtNode == NULL )
87 DBG_ASSERT( pPos->nContent == 0,
88 _ERROR_PREFIX "non-text-node with content" );
90 else
92 DBG_ASSERT( pPos->nContent >= 0 &&
93 pPos->nContent <= pTxtNode->Len(),
94 _ERROR_PREFIX "index behind text" );
98 void lcl_CheckPam( const SwPaM* pPam )
100 DBG_ASSERT( pPam != NULL, _ERROR_PREFIX "illegal argument" );
101 lcl_CheckPosition( pPam->GetPoint() );
102 lcl_CheckPosition( pPam->GetMark() );
105 // check validity of the redline table. Checks redline bounds, and make
106 // sure the redlines are sorted and non-overlapping.
107 void lcl_CheckRedline( const SwDoc* pDoc )
109 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
111 // verify valid redline positions
112 for( USHORT i = 0; i < rTbl.Count(); ++i )
113 lcl_CheckPam( rTbl[ i ] );
115 for( USHORT j = 0; j < rTbl.Count(); ++j )
117 // check for empty redlines
118 DBG_ASSERT( ( *(rTbl[j]->GetPoint()) != *(rTbl[j]->GetMark()) ) ||
119 ( rTbl[j]->GetContentIdx() != NULL ),
120 _ERROR_PREFIX "empty redline" );
123 // verify proper redline sorting
124 for( USHORT n = 1; n < rTbl.Count(); ++n )
126 const SwRedline* pPrev = rTbl[ n-1 ];
127 const SwRedline* pCurrent = rTbl[ n ];
129 // check redline sorting
130 DBG_ASSERT( *pPrev->Start() <= *pCurrent->Start(),
131 _ERROR_PREFIX "not sorted correctly" );
133 // check for overlapping redlines
134 DBG_ASSERT( *pPrev->End() <= *pCurrent->Start(),
135 _ERROR_PREFIX "overlapping redlines" );
139 #define _CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc );
141 void lcl_DebugRedline( const SwDoc* pDoc )
143 static USHORT nWatch = 0;
144 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
145 for( USHORT n = 0; n < rTbl.Count(); ++n )
147 USHORT nDummy = 0;
148 const SwRedline* pCurrent = rTbl[ n ];
149 const SwRedline* pNext = n+1 < rTbl.Count() ? rTbl[ n+1 ] : 0;
150 if( pCurrent == pNext )
151 ++nDummy;
152 if( n == nWatch )
153 ++nDummy; // Possible debugger breakpoint
157 #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
159 #endif
161 SV_IMPL_OP_PTRARR_SORT( _SwRedlineTbl, SwRedlinePtr )
163 RedlineMode_t SwDoc::GetRedlineMode() const
165 return eRedlineMode;
168 void SwDoc::SetRedlineMode( RedlineMode_t eMode )
170 if( eRedlineMode != eMode )
172 if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode)
173 || 0 == (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) )
175 bool bSaveInXMLImportFlag = IsInXMLImport();
176 SetInXMLImport( false );
177 // und dann alles verstecken, anzeigen
178 void (SwRedline::*pFnc)( USHORT ) = 0;
180 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode )
182 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE :
183 pFnc = &SwRedline::Show;
184 break;
185 case nsRedlineMode_t::REDLINE_SHOW_INSERT:
186 pFnc = &SwRedline::Hide;
187 break;
188 case nsRedlineMode_t::REDLINE_SHOW_DELETE:
189 pFnc = &SwRedline::ShowOriginal;
190 break;
192 default:
193 pFnc = &SwRedline::Hide;
194 eMode = (RedlineMode_t)(eMode | nsRedlineMode_t::REDLINE_SHOW_INSERT);
195 break;
198 _CHECK_REDLINE( this )
200 if( pFnc )
201 for( USHORT nLoop = 1; nLoop <= 2; ++nLoop )
202 for( USHORT i = 0; i < pRedlineTbl->Count(); ++i )
203 ((*pRedlineTbl)[ i ]->*pFnc)( nLoop );
204 _CHECK_REDLINE( this )
205 SetInXMLImport( bSaveInXMLImportFlag );
207 eRedlineMode = eMode;
208 SetModified();
212 bool SwDoc::IsRedlineOn() const
214 return IDocumentRedlineAccess::IsRedlineOn(eRedlineMode);
217 bool SwDoc::IsIgnoreRedline() const
219 return (nsRedlineMode_t::REDLINE_IGNORE & eRedlineMode);
222 void SwDoc::SetRedlineMode_intern(RedlineMode_t eMode)
224 eRedlineMode = eMode;
227 const SwRedlineTbl& SwDoc::GetRedlineTbl() const
229 return *pRedlineTbl;
232 bool SwDoc::IsRedlineMove() const
234 return mbIsRedlineMove;
237 void SwDoc::SetRedlineMove(bool bFlag)
239 mbIsRedlineMove = bFlag;
242 const uno::Sequence <sal_Int8>& SwDoc::GetRedlinePassword() const
244 return aRedlinePasswd;
247 inline bool IsPrevPos( const SwPosition rPos1, const SwPosition rPos2 )
249 const SwCntntNode* pCNd;
250 return 0 == rPos2.nContent.GetIndex() &&
251 rPos2.nNode.GetIndex() - 1 == rPos1.nNode.GetIndex() &&
252 0 != ( pCNd = rPos1.nNode.GetNode().GetCntntNode() )
253 ? rPos1.nContent.GetIndex() == pCNd->Len()
254 : false;
257 #ifdef DEBUG
258 bool CheckPosition( const SwPosition* pStt, const SwPosition* pEnd )
260 int nError = 0;
261 SwNode* pSttNode = &pStt->nNode.GetNode();
262 SwNode* pEndNode = &pEnd->nNode.GetNode();
263 SwNode* pSttTab = pSttNode->StartOfSectionNode()->FindTableNode();
264 SwNode* pEndTab = pEndNode->StartOfSectionNode()->FindTableNode();
265 SwNode* pSttStart = pSttNode;
266 while( pSttStart && (!pSttStart->IsStartNode() || pSttStart->IsSectionNode() ||
267 pSttStart->IsTableNode() ) )
268 pSttStart = pSttStart->StartOfSectionNode();
269 SwNode* pEndStart = pEndNode;
270 while( pEndStart && (!pEndStart->IsStartNode() || pEndStart->IsSectionNode() ||
271 pEndStart->IsTableNode() ) )
272 pEndStart = pEndStart->StartOfSectionNode();
273 if( pSttTab != pEndTab )
274 nError = 1;
275 if( !pSttTab && pSttStart != pEndStart )
276 nError |= 2;
277 if( nError )
278 nError += 10;
279 return nError != 0;
281 #endif
285 Text heisst, nicht von Redline "verseuchter" Text.
287 Verhalten von Insert-Redline:
288 - im Text - Redline Object einfuegen
289 - im InsertRedline (eigenes) - ignorieren, bestehendes wird
290 aufgespannt
291 - im InsertRedline (andere) - Insert Redline aufsplitten
292 Redline Object einfuegen
293 - in DeleteRedline - Delete Redline aufsplitten oder
294 am Ende/Anfang verschieben
296 Verhalten von Delete-Redline:
297 - im Text - Redline Object einfuegen
298 - im DeleteRedline (eigenes/andere) - ignorieren
299 - im InsertRedline (eigenes) - ignorieren, Zeichen aber loeschen
300 - im InsertRedline (andere) - Insert Redline aufsplitten
301 Redline Object einfuegen
302 - Ueberlappung von Text und - Text in eigenen Insert loeschen,
303 eigenem Insert im andereren Text aufspannen (bis
304 zum Insert!
305 - Ueberlappung von Text und - Redline Object einfuegen, der
306 anderem Insert andere Insert wird vom Delete
307 ueberlappt
310 bool SwDoc::AppendRedline( SwRedline* pNewRedl, bool bCallDelete )
312 #ifndef PRODUCT
313 SwRedline aCopy( *pNewRedl );
314 #endif
315 bool bError = true;
316 _CHECK_REDLINE( this )
318 if( IsRedlineOn() && !IsShowOriginal( eRedlineMode ) &&
319 pNewRedl->GetAuthorString().Len() )
321 pNewRedl->InvalidateRange();
323 if( mbIsAutoFmtRedline )
325 pNewRedl->SetAutoFmtFlag();
326 if( pAutoFmtRedlnComment && pAutoFmtRedlnComment->Len() )
328 pNewRedl->SetComment( *pAutoFmtRedlnComment );
329 pNewRedl->SetSeqNo( nAutoFmtRedlnCommentNo );
333 SwPosition* pStt = pNewRedl->Start(),
334 * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark()
335 : pNewRedl->GetPoint();
337 SwTxtNode* pTxtNode = pStt->nNode.GetNode().GetTxtNode();
338 if( pTxtNode == NULL )
340 if( pStt->nContent > 0 )
342 DBG_ASSERT( false, "Redline start: non-text-node with content" );
343 pStt->nContent = 0;
346 else
348 if( pStt->nContent > pTxtNode->Len() )
350 DBG_ASSERT( false, "Redline start: index behind text" );
351 pStt->nContent = pTxtNode->Len();
354 pTxtNode = pEnd->nNode.GetNode().GetTxtNode();
355 if( pTxtNode == NULL )
357 if( pEnd->nContent > 0 )
359 DBG_ASSERT( false, "Redline end: non-text-node with content" );
360 pEnd->nContent = 0;
363 else
365 if( pEnd->nContent > pTxtNode->Len() )
367 DBG_ASSERT( false, "Redline end: index behind text" );
368 pEnd->nContent = pTxtNode->Len();
372 if( ( *pStt == *pEnd ) &&
373 ( pNewRedl->GetContentIdx() == NULL ) )
374 { // Do not insert empty redlines
375 delete pNewRedl;
376 return FALSE;
378 BOOL bCompress = FALSE;
379 USHORT n = 0;
380 // zur StartPos das erste Redline suchen
381 if( !GetRedline( *pStt, &n ) && n )
382 --n;
383 bool bDec = false;
385 for( ; pNewRedl && n < pRedlineTbl->Count(); bDec ? n : ++n )
387 bDec = false;
388 #ifdef DVO_TEST
389 _CHECK_REDLINE( this )
390 #endif
392 SwRedline* pRedl = (*pRedlineTbl)[ n ];
393 SwPosition* pRStt = pRedl->Start(),
394 * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
395 : pRedl->GetPoint();
397 // #i8518# remove empty redlines while we're at it
398 if( ( *pRStt == *pREnd ) &&
399 ( pRedl->GetContentIdx() == NULL ) )
401 pRedlineTbl->DeleteAndDestroy(n);
402 continue;
405 SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
407 switch( pNewRedl->GetType() )
409 case nsRedlineType_t::REDLINE_INSERT:
410 switch( pRedl->GetType() )
412 case nsRedlineType_t::REDLINE_INSERT:
413 if( pRedl->IsOwnRedline( *pNewRedl ) )
415 bool bDelete = false;
417 // ggfs. verschmelzen?
418 if( (( POS_BEHIND == eCmpPos &&
419 IsPrevPos( *pREnd, *pStt ) ) ||
420 ( POS_COLLIDE_START == eCmpPos ) ||
421 ( POS_OVERLAP_BEHIND == eCmpPos ) ) &&
422 pRedl->CanCombine( *pNewRedl ) &&
423 ( n+1 >= pRedlineTbl->Count() ||
424 ( *(*pRedlineTbl)[ n+1 ]->Start() >= *pEnd &&
425 *(*pRedlineTbl)[ n+1 ]->Start() != *pREnd ) ) )
427 pRedl->SetEnd( *pEnd, pREnd );
428 if( !pRedl->HasValidRange() )
430 // neu einsortieren
431 pRedlineTbl->Remove( n );
432 pRedlineTbl->Insert( pRedl );
435 bError = false;
436 bDelete = true;
438 else if( (( POS_BEFORE == eCmpPos &&
439 IsPrevPos( *pEnd, *pRStt ) ) ||
440 ( POS_COLLIDE_END == eCmpPos ) ||
441 ( POS_OVERLAP_BEFORE == eCmpPos ) ) &&
442 pRedl->CanCombine( *pNewRedl ) &&
443 ( !n ||
444 *(*pRedlineTbl)[ n-1 ]->End() != *pRStt ))
446 pRedl->SetStart( *pStt, pRStt );
447 // neu einsortieren
448 pRedlineTbl->Remove( n );
449 pRedlineTbl->Insert( pRedl );
451 bError = false;
452 bDelete = true;
454 else if ( POS_OUTSIDE == eCmpPos )
456 // #107164# own insert-over-insert
457 // redlines: just scrap the inside ones
458 pRedlineTbl->Remove( n );
459 bDec = true;
461 // <- #107164#
462 else if( POS_OVERLAP_BEHIND == eCmpPos )
464 *pStt = *pREnd;
465 if( ( *pStt == *pEnd ) &&
466 ( pNewRedl->GetContentIdx() == NULL ) )
467 bDelete = true;
469 else if( POS_OVERLAP_BEFORE == eCmpPos )
471 *pEnd = *pRStt;
472 if( ( *pStt == *pEnd ) &&
473 ( pNewRedl->GetContentIdx() == NULL ) )
474 bDelete = true;
476 else if( POS_INSIDE == eCmpPos || POS_EQUAL == eCmpPos)
477 bDelete = true;
479 if( bDelete )
481 delete pNewRedl, pNewRedl = 0;
482 bCompress = TRUE;
485 else if( POS_INSIDE == eCmpPos )
487 // aufsplitten
488 if( *pEnd != *pREnd )
490 SwRedline* pCpy = new SwRedline( *pRedl );
491 pCpy->SetStart( *pEnd );
492 pRedlineTbl->Insert( pCpy );
494 pRedl->SetEnd( *pStt, pREnd );
495 if( ( *pStt == *pRStt ) &&
496 ( pRedl->GetContentIdx() == NULL ) )
498 pRedlineTbl->DeleteAndDestroy( n );
499 bDec = true;
501 else if( !pRedl->HasValidRange() )
503 // neu einsortieren
504 pRedlineTbl->Remove( n );
505 pRedlineTbl->Insert( pRedl );
508 else if ( POS_OUTSIDE == eCmpPos )
510 // #102366# handle overlapping redlines in broken
511 // documents
513 // split up the new redline, since it covers the
514 // existing redline. Insert the first part, and
515 // progress with the remainder as usual
516 SwRedline* pSplit = new SwRedline( *pNewRedl );
517 pSplit->SetEnd( *pRStt );
518 pNewRedl->SetStart( *pREnd );
519 pRedlineTbl->Insert( pSplit );
520 if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
522 delete pNewRedl;
523 pNewRedl = 0;
524 bCompress = true;
527 else if ( POS_OVERLAP_BEHIND == eCmpPos )
529 // #107164# handle overlapping redlines in broken
530 // documents
531 pNewRedl->SetStart( *pREnd );
533 else if ( POS_OVERLAP_BEFORE == eCmpPos )
535 // #107164# handle overlapping redlines in broken
536 // documents
537 *pEnd = *pRStt;
538 if( ( *pStt == *pEnd ) &&
539 ( pNewRedl->GetContentIdx() == NULL ) )
541 delete pNewRedl;
542 pNewRedl = 0;
543 bCompress = true;
546 break;
547 case nsRedlineType_t::REDLINE_DELETE:
548 if( POS_INSIDE == eCmpPos )
550 // aufsplitten
551 if( *pEnd != *pREnd )
553 SwRedline* pCpy = new SwRedline( *pRedl );
554 pCpy->SetStart( *pEnd );
555 pRedlineTbl->Insert( pCpy );
557 pRedl->SetEnd( *pStt, pREnd );
558 if( ( *pStt == *pRStt ) &&
559 ( pRedl->GetContentIdx() == NULL ) )
561 pRedlineTbl->DeleteAndDestroy( n );
562 bDec = true;
564 else if( !pRedl->HasValidRange() )
566 // neu einsortieren
567 pRedlineTbl->Remove( n );
568 pRedlineTbl->Insert( pRedl, n );
571 else if ( POS_OUTSIDE == eCmpPos )
573 // #102366# handle overlapping redlines in broken
574 // documents
576 // split up the new redline, since it covers the
577 // existing redline. Insert the first part, and
578 // progress with the remainder as usual
579 SwRedline* pSplit = new SwRedline( *pNewRedl );
580 pSplit->SetEnd( *pRStt );
581 pNewRedl->SetStart( *pREnd );
582 pRedlineTbl->Insert( pSplit );
583 if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
585 delete pNewRedl;
586 pNewRedl = 0;
587 bCompress = true;
590 else if ( POS_EQUAL == eCmpPos )
592 // #112895# handle identical redlines in broken
593 // documents - delete old (delete) redline
594 pRedlineTbl->DeleteAndDestroy( n );
595 bDec = true;
597 else if ( POS_OVERLAP_BEHIND == eCmpPos )
598 { // Another workaround for broken redlines (#107164#)
599 pNewRedl->SetStart( *pREnd );
601 break;
602 case nsRedlineType_t::REDLINE_FORMAT:
603 switch( eCmpPos )
605 case POS_OVERLAP_BEFORE:
606 pRedl->SetStart( *pEnd, pRStt );
607 // neu einsortieren
608 pRedlineTbl->Remove( n );
609 pRedlineTbl->Insert( pRedl, n );
610 bDec = true;
611 break;
613 case POS_OVERLAP_BEHIND:
614 pRedl->SetEnd( *pStt, pREnd );
615 if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
617 pRedlineTbl->DeleteAndDestroy( n );
618 bDec = true;
620 break;
622 case POS_EQUAL:
623 case POS_OUTSIDE:
624 // ueberlappt den akt. komplett oder hat gleiche
625 // Ausdehung, dann muss der alte geloescht werden
626 pRedlineTbl->DeleteAndDestroy( n );
627 bDec = true;
628 break;
630 case POS_INSIDE:
631 // ueberlappt den akt. komplett, dann muss
632 // der neue gesplittet oder verkuertzt werden
633 if( *pEnd != *pREnd )
635 if( *pEnd != *pRStt )
637 SwRedline* pNew = new SwRedline( *pRedl );
638 pNew->SetStart( *pEnd );
639 pRedl->SetEnd( *pStt, pREnd );
640 if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
641 pRedlineTbl->DeleteAndDestroy( n );
642 AppendRedline( pNew, bCallDelete );
643 n = 0; // neu Aufsetzen
644 bDec = true;
647 else
648 pRedl->SetEnd( *pStt, pREnd );
649 break;
650 default:
651 break;
653 break;
654 default:
655 break;
657 break;
659 case nsRedlineType_t::REDLINE_DELETE:
660 switch( pRedl->GetType() )
662 case nsRedlineType_t::REDLINE_DELETE:
663 switch( eCmpPos )
665 case POS_OUTSIDE:
667 // ueberlappt den akt. komplett
668 // dann muss der neue gesplittet werden
669 if( *pEnd != *pREnd )
671 SwRedline* pNew = new SwRedline( *pNewRedl );
672 pNew->SetStart( *pREnd );
673 pNewRedl->SetEnd( *pRStt, pEnd );
674 AppendRedline( pNew, bCallDelete );
675 n = 0; // neu Aufsetzen
676 bDec = true;
678 else
679 pNewRedl->SetEnd( *pRStt, pEnd );
681 break;
683 case POS_INSIDE:
684 case POS_EQUAL:
685 delete pNewRedl, pNewRedl = 0;
686 bCompress = TRUE;
687 break;
689 case POS_OVERLAP_BEFORE:
690 case POS_OVERLAP_BEHIND:
691 if( pRedl->IsOwnRedline( *pNewRedl ) &&
692 // 1 == pRedl->GetStackCount() &&
693 pRedl->CanCombine( *pNewRedl ))
695 // dann kann das zusammengefasst werden, sprich
696 // der neue deckt das schon ab.
697 if( POS_OVERLAP_BEHIND == eCmpPos )
698 pNewRedl->SetStart( *pRStt, pStt );
699 else
700 pNewRedl->SetEnd( *pREnd, pEnd );
701 pRedlineTbl->DeleteAndDestroy( n );
702 bDec = true;
704 else if( POS_OVERLAP_BEHIND == eCmpPos )
705 pNewRedl->SetStart( *pREnd, pStt );
706 else
707 pNewRedl->SetEnd( *pRStt, pEnd );
708 break;
710 case POS_COLLIDE_START:
711 case POS_COLLIDE_END:
712 if( pRedl->IsOwnRedline( *pNewRedl ) &&
713 // 1 == pRedl->GetStackCount() &&
714 pRedl->CanCombine( *pNewRedl ) )
716 if( IsHideChanges( eRedlineMode ))
718 // dann erstmal sichtbar machen, bevor
719 // die zusammengefasst werden koennen!
720 // Damit pNew auch beim Verschieben der
721 // Indizies behandelt wird, erstmal
722 // temporaer einfuegen
723 pRedlineTbl->SavePtrInArr( pNewRedl );
724 pRedl->Show();
725 pRedlineTbl->Remove( pRedlineTbl->GetPos(pNewRedl ));
726 pRStt = pRedl->Start();
727 pREnd = pRedl->End();
730 // dann kann das zusammengefasst werden, sprich
731 // der neue deckt das schon ab.
732 if( POS_COLLIDE_START == eCmpPos )
733 pNewRedl->SetStart( *pRStt, pStt );
734 else
735 pNewRedl->SetEnd( *pREnd, pEnd );
737 // delete current (below), and restart process with
738 // previous
739 USHORT nToBeDeleted = n;
740 bDec = true;
742 // #107359# Do it again, Sam!
743 // If you can do it for them, you can do it for me.
744 if( *(pNewRedl->Start()) <= *pREnd )
746 // Whoooah, we just extended the new 'redline'
747 // beyond previous redlines, so better start
748 // again. Of course this is not supposed to
749 // happen, and in an ideal world it doesn't,
750 // but unfortunately this code is buggy and
751 // totally rotten so it does happen and we
752 // better fix it.
753 n = 0;
754 bDec = true;
757 pRedlineTbl->DeleteAndDestroy( nToBeDeleted );
759 break;
760 default:
761 break;
763 break;
765 case nsRedlineType_t::REDLINE_INSERT:
767 // b62341295: Do not throw away redlines
768 // even if they are not allowed to be combined
769 RedlineMode_t eOld = eRedlineMode;
770 if( !( eOld & nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &&
771 pRedl->IsOwnRedline( *pNewRedl ) )
774 // auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig
775 // zusammen fasst! Der ShowMode muss erhalten bleiben!
776 eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
777 switch( eCmpPos )
779 case POS_EQUAL:
780 bCompress = TRUE;
781 pRedlineTbl->DeleteAndDestroy( n );
782 bDec = true;
783 // kein break!
785 case POS_INSIDE:
786 if( bCallDelete )
788 eRedlineMode = (RedlineMode_t)(eRedlineMode | nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES);
790 // #98863# DeleteAndJoin does not yield the
791 // desired result if there is no paragraph to
792 // join with, i.e. at the end of the document.
793 // For this case, we completely delete the
794 // paragraphs (if, of course, we also start on
795 // a paragraph boundary).
796 if( (pStt->nContent == 0) &&
797 pEnd->nNode.GetNode().IsEndNode() )
799 pEnd->nNode--;
800 pEnd->nContent.Assign(
801 pEnd->nNode.GetNode().GetTxtNode(), 0);
802 DelFullPara( *pNewRedl );
804 else
805 DeleteAndJoin( *pNewRedl );
807 bCompress = TRUE;
809 delete pNewRedl, pNewRedl = 0;
810 break;
812 case POS_OUTSIDE:
814 pRedlineTbl->Remove( n );
815 bDec = true;
816 // damit pNew auch beim Verschieben der Indizies
817 // behandelt wird, erstmal temp. einfuegen
818 if( bCallDelete )
820 pRedlineTbl->SavePtrInArr( pNewRedl );
821 DeleteAndJoin( *pRedl );
822 USHORT nFnd = pRedlineTbl->GetPos(pNewRedl );
823 if( USHRT_MAX != nFnd )
824 pRedlineTbl->Remove( nFnd );
825 else
826 pNewRedl = 0;
828 delete pRedl;
830 break;
832 case POS_OVERLAP_BEFORE:
834 SwPaM aPam( *pRStt, *pEnd );
836 if( *pEnd == *pREnd )
837 pRedlineTbl->DeleteAndDestroy( n );
838 else
840 pRedl->SetStart( *pEnd, pRStt );
841 // neu einsortieren
842 pRedlineTbl->Remove( n );
843 pRedlineTbl->Insert( pRedl, n );
846 if( bCallDelete )
848 // damit pNew auch beim Verschieben der Indizies
849 // behandelt wird, erstmal temp. einfuegen
850 pRedlineTbl->SavePtrInArr( pNewRedl );
851 DeleteAndJoin( aPam );
852 USHORT nFnd = pRedlineTbl->GetPos(pNewRedl );
853 if( USHRT_MAX != nFnd )
854 pRedlineTbl->Remove( nFnd );
855 else
856 pNewRedl = 0;
857 n = 0; // neu Aufsetzen
859 bDec = true;
861 break;
863 case POS_OVERLAP_BEHIND:
865 SwPaM aPam( *pStt, *pREnd );
867 if( *pStt == *pRStt )
869 pRedlineTbl->DeleteAndDestroy( n );
870 bDec = true;
872 else
873 pRedl->SetEnd( *pStt, pREnd );
875 if( bCallDelete )
877 // damit pNew auch beim Verschieben der Indizies
878 // behandelt wird, erstmal temp. einfuegen
879 pRedlineTbl->SavePtrInArr( pNewRedl );
880 DeleteAndJoin( aPam );
881 USHORT nFnd = pRedlineTbl->GetPos(pNewRedl );
882 if( USHRT_MAX != nFnd )
883 pRedlineTbl->Remove( nFnd );
884 else
885 pNewRedl = 0;
886 n = 0; // neu Aufsetzen
887 bDec = true;
890 break;
891 default:
892 break;
895 eRedlineMode = eOld;
897 else
899 // it may be necessary to split the existing redline in
900 // two. In this case, pRedl will be changed to cover
901 // only part of it's former range, and pNew will cover
902 // the remainder.
903 SwRedline* pNew = 0;
905 switch( eCmpPos )
907 case POS_EQUAL:
909 pRedl->PushData( *pNewRedl );
910 delete pNewRedl, pNewRedl = 0;
911 if( IsHideChanges( eRedlineMode ))
912 pRedl->Hide();
913 bCompress = TRUE;
915 break;
917 case POS_INSIDE:
919 pNewRedl->PushData( *pRedl, FALSE );
920 if( *pRStt == *pStt )
922 pRedl->SetStart( *pEnd, pRStt );
923 // neu einsortieren
924 pRedlineTbl->Remove( n );
925 pRedlineTbl->Insert( pRedl, n );
926 bDec = true;
928 else
930 if( *pREnd != *pEnd )
932 pNew = new SwRedline( *pRedl );
933 pNew->SetStart( *pEnd );
935 pRedl->SetEnd( *pStt, pREnd );
936 if( !pRedl->HasValidRange() )
938 // neu einsortieren
939 pRedlineTbl->Remove( n );
940 pRedlineTbl->Insert( pRedl, n );
944 break;
946 case POS_OUTSIDE:
948 pRedl->PushData( *pNewRedl );
949 if( *pEnd == *pREnd )
950 pNewRedl->SetEnd( *pRStt, pEnd );
951 else
953 pNew = new SwRedline( *pNewRedl );
954 pNew->SetEnd( *pRStt );
955 pNewRedl->SetStart( *pREnd, pStt );
957 bCompress = TRUE;
959 break;
961 case POS_OVERLAP_BEFORE:
963 if( *pEnd == *pREnd )
965 pRedl->PushData( *pNewRedl );
966 pNewRedl->SetEnd( *pRStt, pEnd );
967 if( IsHideChanges( eRedlineMode ))
969 pRedlineTbl->SavePtrInArr( pNewRedl );
970 pRedl->Hide();
971 pRedlineTbl->Remove(
972 pRedlineTbl->GetPos(pNewRedl ));
975 else
977 pNew = new SwRedline( *pRedl );
978 pNew->PushData( *pNewRedl );
979 pNew->SetEnd( *pEnd );
980 pNewRedl->SetEnd( *pRStt, pEnd );
981 pRedl->SetStart( *pNew->End(), pRStt ) ;
982 // neu einsortieren
983 pRedlineTbl->Remove( n );
984 pRedlineTbl->Insert( pRedl );
985 bDec = true;
988 break;
990 case POS_OVERLAP_BEHIND:
992 if( *pStt == *pRStt )
994 pRedl->PushData( *pNewRedl );
995 pNewRedl->SetStart( *pREnd, pStt );
996 if( IsHideChanges( eRedlineMode ))
998 pRedlineTbl->SavePtrInArr( pNewRedl );
999 pRedl->Hide();
1000 pRedlineTbl->Remove(
1001 pRedlineTbl->GetPos(pNewRedl ));
1004 else
1006 pNew = new SwRedline( *pRedl );
1007 pNew->PushData( *pNewRedl );
1008 pNew->SetStart( *pStt );
1009 pNewRedl->SetStart( *pREnd, pStt );
1010 pRedl->SetEnd( *pNew->Start(), pREnd );
1011 if( !pRedl->HasValidRange() )
1013 // neu einsortieren
1014 pRedlineTbl->Remove( n );
1015 pRedlineTbl->Insert( pRedl );
1019 break;
1020 default:
1021 break;
1024 // insert the pNew part (if it exists)
1025 if( pNew )
1027 // AppendRedline( pNew, bCallDelete );
1028 //sal_Bool bRet =
1029 pRedlineTbl->Insert( pNew );
1031 // pNew must be deleted if Insert() wasn't
1032 // successful. But that can't happen, since pNew is
1033 // part of the original pRedl redline.
1034 // ASSERT( bRet, "Can't insert existing redline?" );
1036 // restart (now with pRedl being split up)
1037 n = 0;
1038 bDec = true;
1042 break;
1044 case nsRedlineType_t::REDLINE_FORMAT:
1045 switch( eCmpPos )
1047 case POS_OVERLAP_BEFORE:
1048 pRedl->SetStart( *pEnd, pRStt );
1049 // neu einsortieren
1050 pRedlineTbl->Remove( n );
1051 pRedlineTbl->Insert( pRedl, n );
1052 bDec = true;
1053 break;
1055 case POS_OVERLAP_BEHIND:
1056 pRedl->SetEnd( *pStt, pREnd );
1057 break;
1059 case POS_EQUAL:
1060 case POS_OUTSIDE:
1061 // ueberlappt den akt. komplett oder hat gleiche
1062 // Ausdehung, dann muss der alte geloescht werden
1063 pRedlineTbl->DeleteAndDestroy( n );
1064 bDec = true;
1065 break;
1067 case POS_INSIDE:
1068 // ueberlappt den akt. komplett, dann muss
1069 // der neue gesplittet oder verkuertzt werden
1070 if( *pEnd != *pREnd )
1072 if( *pEnd != *pRStt )
1074 SwRedline* pNew = new SwRedline( *pRedl );
1075 pNew->SetStart( *pEnd );
1076 pRedl->SetEnd( *pStt, pREnd );
1077 if( ( *pStt == *pRStt ) &&
1078 ( pRedl->GetContentIdx() == NULL ) )
1079 pRedlineTbl->DeleteAndDestroy( n );
1080 AppendRedline( pNew, bCallDelete );
1081 n = 0; // neu Aufsetzen
1082 bDec = true;
1085 else
1086 pRedl->SetEnd( *pStt, pREnd );
1087 break;
1088 default:
1089 break;
1091 break;
1092 default:
1093 break;
1095 break;
1097 case nsRedlineType_t::REDLINE_FORMAT:
1098 switch( pRedl->GetType() )
1100 case nsRedlineType_t::REDLINE_INSERT:
1101 case nsRedlineType_t::REDLINE_DELETE:
1102 switch( eCmpPos )
1104 case POS_OVERLAP_BEFORE:
1105 pNewRedl->SetEnd( *pRStt, pEnd );
1106 break;
1108 case POS_OVERLAP_BEHIND:
1109 pNewRedl->SetStart( *pREnd, pStt );
1110 break;
1112 case POS_EQUAL:
1113 case POS_INSIDE:
1114 // TODO Check if there is any side effect
1115 //delete pNewRedl, pNewRedl = 0;
1116 break;
1118 case POS_OUTSIDE:
1119 // ueberlappt den akt. komplett, dann muss
1120 // der neue gesplittet oder verkuerzt werden
1121 if( *pEnd != *pREnd )
1123 if( *pEnd != *pRStt )
1125 SwRedline* pNew = new SwRedline( *pNewRedl );
1126 pNew->SetStart( *pREnd );
1127 pNewRedl->SetEnd( *pRStt, pEnd );
1128 AppendRedline( pNew, bCallDelete );
1129 n = 0; // neu Aufsetzen
1130 bDec = true;
1133 else
1134 pNewRedl->SetEnd( *pRStt, pEnd );
1135 break;
1136 default:
1137 break;
1139 break;
1140 case nsRedlineType_t::REDLINE_FORMAT:
1141 switch( eCmpPos )
1143 case POS_OUTSIDE:
1144 case POS_EQUAL:
1146 // ueberlappt den akt. komplett oder hat gleiche
1147 // Ausdehnung, dann muss der alte geloescht werden
1148 pRedlineTbl->DeleteAndDestroy( n );
1149 bDec = true;
1151 break;
1153 case POS_INSIDE:
1154 if( pRedl->IsOwnRedline( *pNewRedl ) &&
1155 pRedl->CanCombine( *pNewRedl ))
1156 // ein eigenes kann komplett ignoriert werden
1157 delete pNewRedl, pNewRedl = 0;
1159 else if( *pREnd == *pEnd )
1160 // ansonsten nur den akt. verkuerzen
1161 pRedl->SetEnd( *pStt, pREnd );
1162 else if( *pRStt == *pStt )
1164 // ansonsten nur den akt. verkuerzen
1165 pRedl->SetStart( *pEnd, pRStt );
1166 // neu einsortieren
1167 pRedlineTbl->Remove( n );
1168 pRedlineTbl->Insert( pRedl, n );
1169 bDec = true;
1171 else
1173 // liegt komplett im akt.
1174 // dann muss der gesplittet werden
1175 SwRedline* pNew = new SwRedline( *pRedl );
1176 pNew->SetStart( *pEnd );
1177 pRedl->SetEnd( *pStt, pREnd );
1178 AppendRedline( pNew, bCallDelete );
1179 n = 0; // neu Aufsetzen
1180 bDec = true;
1182 break;
1184 case POS_OVERLAP_BEFORE:
1185 case POS_OVERLAP_BEHIND:
1186 if( pRedl->IsOwnRedline( *pNewRedl ) &&
1187 pRedl->CanCombine( *pNewRedl ))
1189 // dann kann das zusammengefasst werden, sprich
1190 // der neue deckt das schon ab.
1191 if( POS_OVERLAP_BEHIND == eCmpPos )
1192 pNewRedl->SetStart( *pRStt, pStt );
1193 else
1194 pNewRedl->SetEnd( *pREnd, pEnd );
1195 pRedlineTbl->DeleteAndDestroy( n );
1196 bDec = 0;
1198 else if( POS_OVERLAP_BEHIND == eCmpPos )
1199 pNewRedl->SetStart( *pREnd, pStt );
1200 else
1201 pNewRedl->SetEnd( *pRStt, pEnd );
1202 break;
1204 case POS_COLLIDE_END:
1205 if( pRedl->IsOwnRedline( *pNewRedl ) &&
1206 pRedl->CanCombine( *pNewRedl ) && n &&
1207 *(*pRedlineTbl)[ n-1 ]->End() < *pStt )
1209 // dann kann das zusammengefasst werden, sprich
1210 // der neue deckt das schon ab.
1211 pNewRedl->SetEnd( *pREnd, pEnd );
1212 pRedlineTbl->DeleteAndDestroy( n );
1213 bDec = true;
1215 break;
1216 case POS_COLLIDE_START:
1217 if( pRedl->IsOwnRedline( *pNewRedl ) &&
1218 pRedl->CanCombine( *pNewRedl ) &&
1219 n+1 < pRedlineTbl->Count() &&
1220 *(*pRedlineTbl)[ n+1 ]->Start() < *pEnd )
1222 // dann kann das zusammengefasst werden, sprich
1223 // der neue deckt das schon ab.
1224 pNewRedl->SetStart( *pRStt, pStt );
1225 pRedlineTbl->DeleteAndDestroy( n );
1226 bDec = true;
1228 break;
1229 default:
1230 break;
1232 break;
1233 default:
1234 break;
1236 break;
1239 case nsRedlineType_t::REDLINE_FMTCOLL:
1240 // wie soll das verhalten sein????
1241 // erstmal so einfuegen
1242 break;
1243 default:
1244 break;
1248 if( pNewRedl )
1250 if( ( *pStt == *pEnd ) &&
1251 ( pNewRedl->GetContentIdx() == NULL ) )
1252 { // Do not insert empty redlines
1253 delete pNewRedl;
1254 pNewRedl = 0;
1256 else
1257 pRedlineTbl->Insert( pNewRedl );
1260 if( bCompress )
1261 CompressRedlines();
1263 else
1265 if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
1267 RedlineMode_t eOld = eRedlineMode;
1268 // auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig
1269 // zusammen fasst! Der ShowMode muss erhalten bleiben!
1270 eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
1271 DeleteAndJoin( *pNewRedl );
1272 eRedlineMode = eOld;
1274 delete pNewRedl, pNewRedl = 0;
1276 _CHECK_REDLINE( this )
1278 return ( 0 != pNewRedl ) || !bError;
1281 void SwDoc::CompressRedlines()
1283 _CHECK_REDLINE( this )
1285 void (SwRedline::*pFnc)(USHORT) = 0;
1286 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode )
1288 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
1289 pFnc = &SwRedline::Show;
1290 break;
1291 case nsRedlineMode_t::REDLINE_SHOW_INSERT:
1292 pFnc = &SwRedline::Hide;
1293 break;
1296 // versuche gleiche zusammenzufassen
1297 for( USHORT n = 1; n < pRedlineTbl->Count(); ++n )
1299 SwRedline* pPrev = (*pRedlineTbl)[ n-1 ],
1300 * pCur = (*pRedlineTbl)[ n ];
1301 const SwPosition* pPrevStt = pPrev->Start(),
1302 * pPrevEnd = pPrevStt == pPrev->GetPoint()
1303 ? pPrev->GetMark() : pPrev->GetPoint();
1304 const SwPosition* pCurStt = pCur->Start(),
1305 * pCurEnd = pCurStt == pCur->GetPoint()
1306 ? pCur->GetMark() : pCur->GetPoint();
1307 if( *pPrevEnd == *pCurStt && pPrev->CanCombine( *pCur ) &&
1308 pPrevStt->nNode.GetNode().StartOfSectionNode() ==
1309 pCurEnd->nNode.GetNode().StartOfSectionNode() &&
1310 !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() )
1312 // dann koennen die zusammen gefasst werden
1313 pPrev->Show();
1314 pCur->Show();
1316 pPrev->SetEnd( *pCur->End() );
1317 pRedlineTbl->DeleteAndDestroy( n );
1318 --n;
1319 if( pFnc )
1320 (pPrev->*pFnc)(0);
1323 _CHECK_REDLINE( this )
1326 bool SwDoc::SplitRedline( const SwPaM& rRange )
1328 BOOL bChg = FALSE;
1329 USHORT n = 0;
1330 const SwPosition* pStt = rRange.Start(),
1331 * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
1332 : rRange.GetPoint();
1333 GetRedline( *pStt, &n );
1334 for( ; n < pRedlineTbl->Count() ; ++n )
1336 SwRedline* pTmp = (*pRedlineTbl)[ n ];
1337 SwPosition* pTStt = pTmp->Start(),
1338 * pTEnd = pTStt == pTmp->GetPoint() ? pTmp->GetMark()
1339 : pTmp->GetPoint();
1340 if( *pTStt <= *pStt && *pStt <= *pTEnd &&
1341 *pTStt <= *pEnd && *pEnd <= *pTEnd )
1343 bChg = TRUE;
1344 int nn = 0;
1345 if( *pStt == *pTStt )
1346 nn += 1;
1347 if( *pEnd == *pTEnd )
1348 nn += 2;
1350 SwRedline* pNew = 0;
1351 switch( nn )
1353 case 0:
1354 pNew = new SwRedline( *pTmp );
1355 pTmp->SetEnd( *pStt, pTEnd );
1356 pNew->SetStart( *pEnd );
1357 break;
1359 case 1:
1360 *pTStt = *pEnd;
1361 break;
1363 case 2:
1364 *pTEnd = *pStt;
1365 break;
1367 case 3:
1368 pTmp->InvalidateRange();
1369 pRedlineTbl->DeleteAndDestroy( n-- );
1370 pTmp = 0;
1371 break;
1373 if( pTmp && !pTmp->HasValidRange() )
1375 // neu einsortieren
1376 pRedlineTbl->Remove( n );
1377 pRedlineTbl->Insert( pTmp, n );
1379 if( pNew )
1380 pRedlineTbl->Insert( pNew, n );
1382 else if( *pEnd < *pTStt )
1383 break;
1385 return bChg;
1388 bool SwDoc::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
1389 USHORT nDelType )
1391 if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & eRedlineMode ||
1392 !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
1393 return FALSE;
1395 BOOL bChg = FALSE;
1397 if( bSaveInUndo && DoesUndo() )
1399 SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange );
1400 if( pUndo->GetRedlSaveCount() )
1402 ClearRedo();
1403 AppendUndo( pUndo );
1405 else
1406 delete pUndo;
1409 const SwPosition* pStt = rRange.Start(),
1410 * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
1411 : rRange.GetPoint();
1412 USHORT n = 0;
1413 GetRedline( *pStt, &n );
1414 for( ; n < pRedlineTbl->Count() ; ++n )
1416 SwRedline* pRedl = (*pRedlineTbl)[ n ];
1417 if( USHRT_MAX != nDelType && nDelType != pRedl->GetType() )
1418 continue;
1420 SwPosition* pRStt = pRedl->Start(),
1421 * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
1422 : pRedl->GetPoint();
1423 BOOL bDel = FALSE;
1424 switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
1426 case POS_EQUAL:
1427 case POS_OUTSIDE:
1428 bDel = TRUE;
1429 break;
1431 case POS_OVERLAP_BEFORE:
1432 if( *pEnd == *pREnd )
1433 bDel = TRUE;
1434 else
1436 pRedl->InvalidateRange();
1437 pRedl->SetStart( *pEnd, pRStt );
1438 // neu einsortieren
1439 pRedlineTbl->Remove( n );
1440 pRedlineTbl->Insert( pRedl );
1441 --n;
1443 break;
1445 case POS_OVERLAP_BEHIND:
1446 if( *pStt == *pRStt )
1447 bDel = TRUE;
1448 else
1450 pRedl->InvalidateRange();
1451 pRedl->SetEnd( *pStt, pREnd );
1452 if( !pRedl->HasValidRange() )
1454 // neu einsortieren
1455 pRedlineTbl->Remove( n );
1456 pRedlineTbl->Insert( pRedl );
1457 --n;
1460 break;
1462 case POS_INSIDE:
1464 // der muss gesplittet werden
1465 pRedl->InvalidateRange();
1466 if( *pRStt == *pStt )
1468 pRedl->SetStart( *pEnd, pRStt );
1469 // neu einsortieren
1470 pRedlineTbl->Remove( n );
1471 pRedlineTbl->Insert( pRedl );
1472 --n;
1474 else
1476 SwRedline* pCpy;
1477 if( *pREnd != *pEnd )
1479 pCpy = new SwRedline( *pRedl );
1480 pCpy->SetStart( *pEnd );
1482 else
1483 pCpy = 0;
1484 pRedl->SetEnd( *pStt, pREnd );
1485 if( !pRedl->HasValidRange() )
1487 // neu einsortieren
1488 pRedlineTbl->Remove( pRedlineTbl->GetPos( pRedl ));
1489 pRedlineTbl->Insert( pRedl );
1490 --n;
1492 if( pCpy )
1493 pRedlineTbl->Insert( pCpy );
1496 break;
1498 case POS_COLLIDE_END:
1499 case POS_BEFORE:
1500 n = pRedlineTbl->Count();
1501 break;
1502 default:
1503 break;
1506 if( bDel )
1508 pRedl->InvalidateRange();
1509 pRedlineTbl->DeleteAndDestroy( n-- );
1510 bChg = TRUE;
1514 if( bChg )
1515 SetModified();
1517 return bChg;
1520 bool SwDoc::DeleteRedline( const SwStartNode& rNode, bool bSaveInUndo,
1521 USHORT nDelType )
1523 SwPaM aTemp(*rNode.EndOfSectionNode(), rNode);
1524 return DeleteRedline(aTemp, bSaveInUndo, nDelType);
1527 USHORT SwDoc::GetRedlinePos( const SwNode& rNd, USHORT nType ) const
1529 const ULONG nNdIdx = rNd.GetIndex();
1530 for( USHORT n = 0; n < pRedlineTbl->Count() ; ++n )
1532 const SwRedline* pTmp = (*pRedlineTbl)[ n ];
1533 ULONG nPt = pTmp->GetPoint()->nNode.GetIndex(),
1534 nMk = pTmp->GetMark()->nNode.GetIndex();
1535 if( nPt < nMk ) { long nTmp = nMk; nMk = nPt; nPt = nTmp; }
1537 if( ( USHRT_MAX == nType || nType == pTmp->GetType()) &&
1538 nMk <= nNdIdx && nNdIdx <= nPt )
1539 return n;
1541 if( nMk > nNdIdx )
1542 break;
1544 return USHRT_MAX;
1547 const SwRedline* SwDoc::GetRedline( const SwPosition& rPos,
1548 USHORT* pFndPos ) const
1550 USHORT nO = pRedlineTbl->Count(), nM, nU = 0;
1551 if( nO > 0 )
1553 nO--;
1554 while( nU <= nO )
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 ) )
1566 /* #107318# returned wrong redline ???*/
1567 while( nM && rPos == *(*pRedlineTbl)[ nM - 1 ]->End() &&
1568 rPos == *(*pRedlineTbl)[ nM - 1 ]->Start() )
1570 --nM;
1571 pRedl = (*pRedlineTbl)[ nM ];
1574 if( pFndPos )
1575 *pFndPos = nM;
1576 return pRedl;
1578 else if( *pEnd <= rPos )
1579 nU = nM + 1;
1580 else if( nM == 0 )
1582 if( pFndPos )
1583 *pFndPos = nU;
1584 return 0;
1586 else
1587 nO = nM - 1;
1590 if( pFndPos )
1591 *pFndPos = nU;
1592 return 0;
1595 typedef BOOL (*Fn_AcceptReject)( SwRedlineTbl& rArr, USHORT& rPos,
1596 BOOL bCallDelete,
1597 const SwPosition* pSttRng,
1598 const SwPosition* pEndRng);
1600 BOOL lcl_AcceptRedline( SwRedlineTbl& rArr, USHORT& rPos,
1601 BOOL bCallDelete,
1602 const SwPosition* pSttRng = 0,
1603 const SwPosition* pEndRng = 0 )
1605 BOOL bRet = TRUE;
1606 SwRedline* pRedl = rArr[ rPos ];
1607 SwPosition *pRStt = 0, *pREnd = 0;
1608 SwComparePosition eCmp = POS_OUTSIDE;
1609 if( pSttRng && pEndRng )
1611 pRStt = pRedl->Start();
1612 pREnd = pRedl->End();
1613 eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
1616 pRedl->InvalidateRange();
1618 switch( pRedl->GetType() )
1620 case nsRedlineType_t::REDLINE_INSERT:
1621 case nsRedlineType_t::REDLINE_FORMAT:
1623 BOOL bCheck = FALSE, bReplace = FALSE;
1624 switch( eCmp )
1626 case POS_INSIDE:
1627 if( *pSttRng == *pRStt )
1628 pRedl->SetStart( *pEndRng, pRStt );
1629 else
1631 if( *pEndRng != *pREnd )
1633 // aufsplitten
1634 SwRedline* pNew = new SwRedline( *pRedl );
1635 pNew->SetStart( *pEndRng );
1636 rArr.Insert( pNew ); ++rPos;
1638 pRedl->SetEnd( *pSttRng, pREnd );
1639 bCheck = TRUE;
1641 break;
1643 case POS_OVERLAP_BEFORE:
1644 pRedl->SetStart( *pEndRng, pRStt );
1645 bReplace = TRUE;
1646 break;
1648 case POS_OVERLAP_BEHIND:
1649 pRedl->SetEnd( *pSttRng, pREnd );
1650 bCheck = TRUE;
1651 break;
1653 case POS_OUTSIDE:
1654 case POS_EQUAL:
1655 rArr.DeleteAndDestroy( rPos-- );
1656 break;
1658 default:
1659 bRet = FALSE;
1662 if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
1664 // neu einsortieren
1665 rArr.Remove( rArr.GetPos( pRedl ));
1666 rArr.Insert( pRedl );
1669 break;
1670 case nsRedlineType_t::REDLINE_DELETE:
1672 SwDoc& rDoc = *pRedl->GetDoc();
1673 const SwPosition *pDelStt = 0, *pDelEnd = 0;
1674 BOOL bDelRedl = FALSE;
1675 switch( eCmp )
1677 case POS_INSIDE:
1678 if( bCallDelete )
1680 pDelStt = pSttRng;
1681 pDelEnd = pEndRng;
1683 break;
1685 case POS_OVERLAP_BEFORE:
1686 if( bCallDelete )
1688 pDelStt = pRStt;
1689 pDelEnd = pEndRng;
1691 break;
1692 case POS_OVERLAP_BEHIND:
1693 if( bCallDelete )
1695 pDelStt = pREnd;
1696 pDelEnd = pSttRng;
1698 break;
1700 case POS_OUTSIDE:
1701 case POS_EQUAL:
1703 rArr.Remove( rPos-- );
1704 bDelRedl = TRUE;
1705 if( bCallDelete )
1707 pDelStt = pRedl->Start();
1708 pDelEnd = pRedl->End();
1711 break;
1712 default:
1713 bRet = FALSE;
1716 if( pDelStt && pDelEnd )
1718 SwPaM aPam( *pDelStt, *pDelEnd );
1719 SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
1720 SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
1722 if( bDelRedl )
1723 delete pRedl;
1725 RedlineMode_t eOld = rDoc.GetRedlineMode();
1726 rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
1728 if( pCSttNd && pCEndNd )
1729 rDoc.DeleteAndJoin( aPam );
1730 else
1732 rDoc.DeleteRange( aPam );
1734 if( pCSttNd && !pCEndNd )
1736 aPam.GetBound( TRUE ).nContent.Assign( 0, 0 );
1737 aPam.GetBound( FALSE ).nContent.Assign( 0, 0 );
1738 aPam.DeleteMark();
1739 rDoc.DelFullPara( aPam );
1742 rDoc.SetRedlineMode_intern( eOld );
1744 else if( bDelRedl )
1745 delete pRedl;
1747 break;
1749 case nsRedlineType_t::REDLINE_FMTCOLL:
1750 rArr.DeleteAndDestroy( rPos-- );
1751 break;
1753 default:
1754 bRet = FALSE;
1756 return bRet;
1759 BOOL lcl_RejectRedline( SwRedlineTbl& rArr, USHORT& rPos,
1760 BOOL bCallDelete,
1761 const SwPosition* pSttRng = 0,
1762 const SwPosition* pEndRng = 0 )
1764 BOOL bRet = TRUE;
1765 SwRedline* pRedl = rArr[ rPos ];
1766 SwPosition *pRStt = 0, *pREnd = 0;
1767 SwComparePosition eCmp = POS_OUTSIDE;
1768 if( pSttRng && pEndRng )
1770 pRStt = pRedl->Start();
1771 pREnd = pRedl->End();
1772 eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
1775 pRedl->InvalidateRange();
1777 switch( pRedl->GetType() )
1779 case nsRedlineType_t::REDLINE_INSERT:
1781 SwDoc& rDoc = *pRedl->GetDoc();
1782 const SwPosition *pDelStt = 0, *pDelEnd = 0;
1783 BOOL bDelRedl = FALSE;
1784 switch( eCmp )
1786 case POS_INSIDE:
1787 if( bCallDelete )
1789 pDelStt = pSttRng;
1790 pDelEnd = pEndRng;
1792 break;
1794 case POS_OVERLAP_BEFORE:
1795 if( bCallDelete )
1797 pDelStt = pRStt;
1798 pDelEnd = pEndRng;
1800 break;
1801 case POS_OVERLAP_BEHIND:
1802 if( bCallDelete )
1804 pDelStt = pREnd;
1805 pDelEnd = pSttRng;
1807 break;
1808 case POS_OUTSIDE:
1809 case POS_EQUAL:
1811 // dann den Bereich wieder loeschen
1812 rArr.Remove( rPos-- );
1813 bDelRedl = TRUE;
1814 if( bCallDelete )
1816 pDelStt = pRedl->Start();
1817 pDelEnd = pRedl->End();
1820 break;
1822 default:
1823 bRet = FALSE;
1825 if( pDelStt && pDelEnd )
1827 SwPaM aPam( *pDelStt, *pDelEnd );
1829 SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
1830 SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
1832 if( bDelRedl )
1833 delete pRedl;
1835 RedlineMode_t eOld = rDoc.GetRedlineMode();
1836 rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
1838 if( pCSttNd && pCEndNd )
1839 rDoc.DeleteAndJoin( aPam );
1840 else
1842 rDoc.DeleteRange( aPam );
1844 if( pCSttNd && !pCEndNd )
1846 aPam.GetBound( TRUE ).nContent.Assign( 0, 0 );
1847 aPam.GetBound( FALSE ).nContent.Assign( 0, 0 );
1848 aPam.DeleteMark();
1849 rDoc.DelFullPara( aPam );
1852 rDoc.SetRedlineMode_intern( eOld );
1854 else if( bDelRedl )
1855 delete pRedl;
1857 break;
1858 case nsRedlineType_t::REDLINE_DELETE:
1860 SwRedline* pNew = 0;
1861 BOOL bCheck = FALSE, bReplace = FALSE;
1863 switch( eCmp )
1865 case POS_INSIDE:
1867 if( 1 < pRedl->GetStackCount() )
1869 pNew = new SwRedline( *pRedl );
1870 pNew->PopData();
1872 if( *pSttRng == *pRStt )
1874 pRedl->SetStart( *pEndRng, pRStt );
1875 bReplace = TRUE;
1876 if( pNew )
1877 pNew->SetEnd( *pEndRng );
1879 else
1881 if( *pEndRng != *pREnd )
1883 // aufsplitten
1884 SwRedline* pCpy = new SwRedline( *pRedl );
1885 pCpy->SetStart( *pEndRng );
1886 rArr.Insert( pCpy ); ++rPos;
1887 if( pNew )
1888 pNew->SetEnd( *pEndRng );
1891 pRedl->SetEnd( *pSttRng, pREnd );
1892 bCheck = TRUE;
1893 if( pNew )
1894 pNew->SetStart( *pSttRng );
1897 break;
1899 case POS_OVERLAP_BEFORE:
1900 if( 1 < pRedl->GetStackCount() )
1902 pNew = new SwRedline( *pRedl );
1903 pNew->PopData();
1905 pRedl->SetStart( *pEndRng, pRStt );
1906 bReplace = TRUE;
1907 if( pNew )
1908 pNew->SetEnd( *pEndRng );
1909 break;
1911 case POS_OVERLAP_BEHIND:
1912 if( 1 < pRedl->GetStackCount() )
1914 pNew = new SwRedline( *pRedl );
1915 pNew->PopData();
1917 pRedl->SetEnd( *pSttRng, pREnd );
1918 bCheck = TRUE;
1919 if( pNew )
1920 pNew->SetStart( *pSttRng );
1921 break;
1923 case POS_OUTSIDE:
1924 case POS_EQUAL:
1925 if( !pRedl->PopData() )
1926 // das RedlineObject loeschen reicht
1927 rArr.DeleteAndDestroy( rPos-- );
1928 break;
1930 default:
1931 bRet = FALSE;
1934 if( pNew )
1936 rArr.Insert( pNew ); ++rPos;
1939 if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
1941 // neu einsortieren
1942 rArr.Remove( rArr.GetPos( pRedl ));
1943 rArr.Insert( pRedl );
1946 break;
1948 case nsRedlineType_t::REDLINE_FORMAT:
1949 case nsRedlineType_t::REDLINE_FMTCOLL:
1951 if( pRedl->GetExtraData() )
1952 pRedl->GetExtraData()->Reject( *pRedl );
1953 rArr.DeleteAndDestroy( rPos-- );
1955 break;
1957 default:
1958 bRet = FALSE;
1960 return bRet;
1964 const SwRedline* lcl_FindCurrRedline( const SwPosition& rSttPos,
1965 USHORT& rPos,
1966 BOOL bNext = TRUE )
1968 const SwRedline* pFnd = 0;
1969 const SwRedlineTbl& rArr = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl();
1970 for( ; rPos < rArr.Count() ; ++rPos )
1972 const SwRedline* pTmp = rArr[ rPos ];
1973 if( pTmp->HasMark() && pTmp->IsVisible() )
1975 const SwPosition* pRStt = pTmp->Start(),
1976 * pREnd = pRStt == pTmp->GetPoint() ? pTmp->GetMark()
1977 : pTmp->GetPoint();
1978 if( bNext ? *pRStt <= rSttPos : *pRStt < rSttPos )
1980 if( bNext ? *pREnd > rSttPos : *pREnd >= rSttPos )
1982 pFnd = pTmp;
1983 break;
1986 else
1987 break;
1990 return pFnd;
1993 // #111827#
1994 int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject,
1995 SwRedlineTbl& rArr, BOOL bCallDelete,
1996 const SwPaM& rPam)
1998 USHORT n = 0;
1999 int nCount = 0; // #111827#
2001 const SwPosition* pStt = rPam.Start(),
2002 * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
2003 : rPam.GetPoint();
2004 const SwRedline* pFnd = lcl_FindCurrRedline( *pStt, n, TRUE );
2005 if( pFnd && // neu ein Teil davon?
2006 ( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd ))
2008 // dann nur die TeilSelektion aufheben
2009 if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
2010 nCount++; // #111827#
2011 ++n;
2014 for( ; n < rArr.Count(); ++n )
2016 SwRedline* pTmp = rArr[ n ];
2017 if( pTmp->HasMark() && pTmp->IsVisible() )
2019 if( *pTmp->End() <= *pEnd )
2021 if( (*fn_AcceptReject)( rArr, n, bCallDelete, 0, 0 ))
2022 nCount++; // #111827#
2024 else
2026 if( *pTmp->Start() < *pEnd )
2028 // dann nur in der TeilSelektion aufheben
2029 if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
2030 nCount++; // #111827#
2032 break;
2036 return nCount; // #111827#
2039 void lcl_AdjustRedlineRange( SwPaM& rPam )
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() )
2051 const SwRedline* pRedl = pDoc->GetRedline( *pStt, 0 );
2052 if( pRedl )
2054 const SwPosition* pRStt = pRedl->Start();
2055 if( !pRStt->nContent.GetIndex() && pRStt->nNode.GetIndex() ==
2056 pStt->nNode.GetIndex() - 1 )
2057 *pStt = *pRStt;
2060 if( pEnd->nNode.GetNode().IsCntntNode() &&
2061 !pDoc->GetNodes()[ pEnd->nNode.GetIndex() + 1 ]->IsCntntNode() &&
2062 pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() )
2064 const SwRedline* pRedl = pDoc->GetRedline( *pEnd, 0 );
2065 if( pRedl )
2067 const SwPosition* pREnd = pRedl->End();
2068 if( !pREnd->nContent.GetIndex() && pREnd->nNode.GetIndex() ==
2069 pEnd->nNode.GetIndex() + 1 )
2070 *pEnd = *pREnd;
2076 bool SwDoc::AcceptRedline( USHORT nPos, bool bCallDelete )
2078 BOOL bRet = FALSE;
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));
2085 SwRedline* pTmp = (*pRedlineTbl)[ nPos ];
2086 if( pTmp->HasMark() && pTmp->IsVisible() )
2088 if( DoesUndo() )
2090 // #111827#
2091 SwRewriter aRewriter;
2093 aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr());
2094 StartUndo( UNDO_ACCEPT_REDLINE, &aRewriter);
2097 int nLoopCnt = 2;
2098 USHORT nSeqNo = pTmp->GetSeqNo();
2100 do {
2102 if( DoesUndo() )
2103 AppendUndo( new SwUndoAcceptRedline( *pTmp ));
2105 bRet |= lcl_AcceptRedline( *pRedlineTbl, nPos, bCallDelete );
2107 if( nSeqNo )
2109 if( USHRT_MAX == nPos )
2110 nPos = 0;
2111 USHORT nFndPos = 2 == nLoopCnt
2112 ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
2113 : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
2114 if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
2115 USHRT_MAX != ( nFndPos =
2116 pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
2117 pTmp = (*pRedlineTbl)[ nPos = nFndPos ];
2118 else
2119 nLoopCnt = 0;
2121 else
2122 nLoopCnt = 0;
2124 } while( nLoopCnt );
2126 if( bRet )
2128 CompressRedlines();
2129 SetModified();
2132 if( DoesUndo() )
2133 EndUndo( UNDO_ACCEPT_REDLINE, NULL );
2135 return bRet;
2138 bool SwDoc::AcceptRedline( const SwPaM& rPam, bool bCallDelete )
2140 // aufjedenfall auf sichtbar umschalten
2141 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
2142 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
2143 SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
2145 // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
2146 // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
2147 // die Selection auf diese
2148 SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2149 lcl_AdjustRedlineRange( aPam );
2151 if( DoesUndo() )
2153 StartUndo( UNDO_ACCEPT_REDLINE, NULL );
2154 AppendUndo( new SwUndoAcceptRedline( aPam ));
2157 // #111827#
2158 int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *pRedlineTbl,
2159 bCallDelete, aPam );
2160 if( nRet > 0 )
2162 CompressRedlines();
2163 SetModified();
2165 if( DoesUndo() )
2167 // #111827#
2168 String aTmpStr;
2171 SwRewriter aRewriter;
2172 aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet));
2173 aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
2176 SwRewriter aRewriter;
2177 aRewriter.AddRule(UNDO_ARG1, aTmpStr);
2179 EndUndo( UNDO_ACCEPT_REDLINE, &aRewriter );
2181 return nRet != 0;
2184 bool SwDoc::RejectRedline( USHORT nPos, bool bCallDelete )
2186 BOOL bRet = FALSE;
2188 // aufjedenfall auf sichtbar umschalten
2189 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
2190 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
2191 SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
2193 SwRedline* pTmp = (*pRedlineTbl)[ nPos ];
2194 if( pTmp->HasMark() && pTmp->IsVisible() )
2196 if( DoesUndo() )
2198 // #111827#
2199 SwRewriter aRewriter;
2201 aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr());
2202 StartUndo( UNDO_REJECT_REDLINE, NULL );
2205 int nLoopCnt = 2;
2206 USHORT nSeqNo = pTmp->GetSeqNo();
2208 do {
2210 if( DoesUndo() )
2211 AppendUndo( new SwUndoRejectRedline( *pTmp ));
2213 bRet |= lcl_RejectRedline( *pRedlineTbl, nPos, bCallDelete );
2215 if( nSeqNo )
2217 if( USHRT_MAX == nPos )
2218 nPos = 0;
2219 USHORT nFndPos = 2 == nLoopCnt
2220 ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
2221 : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
2222 if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
2223 USHRT_MAX != ( nFndPos =
2224 pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
2225 pTmp = (*pRedlineTbl)[ nPos = nFndPos ];
2226 else
2227 nLoopCnt = 0;
2229 else
2230 nLoopCnt = 0;
2232 } while( nLoopCnt );
2234 if( bRet )
2236 CompressRedlines();
2237 SetModified();
2240 if( DoesUndo() )
2241 EndUndo( UNDO_REJECT_REDLINE, NULL );
2243 return bRet;
2246 bool SwDoc::RejectRedline( const SwPaM& rPam, bool bCallDelete )
2248 // aufjedenfall auf sichtbar umschalten
2249 if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
2250 (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
2251 SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
2253 // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
2254 // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
2255 // die Selection auf diese
2256 SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2257 lcl_AdjustRedlineRange( aPam );
2259 if( DoesUndo() )
2261 StartUndo( UNDO_REJECT_REDLINE, NULL );
2262 AppendUndo( new SwUndoRejectRedline( aPam ));
2265 // #111827#
2266 int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *pRedlineTbl,
2267 bCallDelete, aPam );
2268 if( nRet > 0 )
2270 CompressRedlines();
2271 SetModified();
2273 if( DoesUndo() )
2275 // #111827#
2276 String aTmpStr;
2279 SwRewriter aRewriter;
2280 aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet));
2281 aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
2284 SwRewriter aRewriter;
2285 aRewriter.AddRule(UNDO_ARG1, aTmpStr);
2287 EndUndo( UNDO_REJECT_REDLINE, &aRewriter );
2290 return nRet != 0;
2293 const SwRedline* SwDoc::SelNextRedline( SwPaM& rPam ) const
2295 rPam.DeleteMark();
2296 rPam.SetMark();
2298 SwPosition& rSttPos = *rPam.GetPoint();
2299 SwPosition aSavePos( rSttPos );
2300 BOOL bRestart;
2302 // sollte die StartPos auf dem letzen gueligen ContentNode stehen,
2303 // dann aufjedenfall das naechste Redline nehmen
2304 USHORT n = 0;
2305 const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, TRUE );
2306 if( pFnd )
2308 const SwPosition* pEnd = pFnd->End();
2309 if( !pEnd->nNode.GetNode().IsCntntNode() )
2311 SwNodeIndex aTmp( pEnd->nNode );
2312 SwCntntNode* pCNd = GetNodes().GoPrevSection( &aTmp );
2313 if( !pCNd || ( aTmp == rSttPos.nNode &&
2314 pCNd->Len() == rSttPos.nContent.GetIndex() ))
2315 pFnd = 0;
2317 if( pFnd )
2318 rSttPos = *pFnd->End();
2321 do {
2322 bRestart = FALSE;
2324 for( ; !pFnd && n < pRedlineTbl->Count(); ++n )
2326 pFnd = (*pRedlineTbl)[ n ];
2327 if( pFnd->HasMark() && pFnd->IsVisible() )
2329 *rPam.GetMark() = *pFnd->Start();
2330 rSttPos = *pFnd->End();
2331 break;
2333 else
2334 pFnd = 0;
2337 if( pFnd )
2339 // alle vom gleichen Typ und Author, die hinter einander liegen
2340 // zu einer Selektion zusammenfassen.
2341 const SwPosition* pPrevEnd = pFnd->End();
2342 while( ++n < pRedlineTbl->Count() )
2344 const SwRedline* pTmp = (*pRedlineTbl)[ n ];
2345 if( pTmp->HasMark() && pTmp->IsVisible() )
2347 const SwPosition *pRStt;
2348 if( pFnd->GetType() == pTmp->GetType() &&
2349 pFnd->GetAuthor() == pTmp->GetAuthor() &&
2350 ( *pPrevEnd == *( pRStt = pTmp->Start() ) ||
2351 IsPrevPos( *pPrevEnd, *pRStt )) )
2353 pPrevEnd = pTmp->End();
2354 rSttPos = *pPrevEnd;
2356 else
2357 break;
2362 if( pFnd )
2364 const SwRedline* pSaveFnd = pFnd;
2366 SwCntntNode* pCNd;
2367 SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
2368 if( !pIdx->GetNode().IsCntntNode() &&
2369 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) )
2371 if( *pIdx <= rPam.GetPoint()->nNode )
2372 rPam.GetMark()->nContent.Assign( pCNd, 0 );
2373 else
2374 pFnd = 0;
2377 if( pFnd )
2379 pIdx = &rPam.GetPoint()->nNode;
2380 if( !pIdx->GetNode().IsCntntNode() &&
2381 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) )
2383 if( *pIdx >= rPam.GetMark()->nNode )
2384 rPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
2385 else
2386 pFnd = 0;
2390 if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
2392 if( n < pRedlineTbl->Count() )
2394 bRestart = TRUE;
2395 *rPam.GetPoint() = *pSaveFnd->End();
2397 else
2399 rPam.DeleteMark();
2400 *rPam.GetPoint() = aSavePos;
2402 pFnd = 0;
2405 } while( bRestart );
2407 return pFnd;
2410 const SwRedline* SwDoc::SelPrevRedline( SwPaM& rPam ) const
2412 rPam.DeleteMark();
2413 rPam.SetMark();
2415 SwPosition& rSttPos = *rPam.GetPoint();
2416 SwPosition aSavePos( rSttPos );
2417 BOOL bRestart;
2419 // sollte die StartPos auf dem ersten gueligen ContentNode stehen,
2420 // dann aufjedenfall das vorherige Redline nehmen
2421 USHORT n = 0;
2422 const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, FALSE );
2423 if( pFnd )
2425 const SwPosition* pStt = pFnd->Start();
2426 if( !pStt->nNode.GetNode().IsCntntNode() )
2428 SwNodeIndex aTmp( pStt->nNode );
2429 SwCntntNode* pCNd = GetNodes().GoNextSection( &aTmp );
2430 if( !pCNd || ( aTmp == rSttPos.nNode &&
2431 !rSttPos.nContent.GetIndex() ))
2432 pFnd = 0;
2434 if( pFnd )
2435 rSttPos = *pFnd->Start();
2438 do {
2439 bRestart = FALSE;
2441 while( !pFnd && 0 < n )
2443 pFnd = (*pRedlineTbl)[ --n ];
2444 if( pFnd->HasMark() && pFnd->IsVisible() )
2446 *rPam.GetMark() = *pFnd->End();
2447 rSttPos = *pFnd->Start();
2449 else
2450 pFnd = 0;
2453 if( pFnd )
2455 // alle vom gleichen Typ und Author, die hinter einander liegen
2456 // zu einer Selektion zusammenfassen.
2457 const SwPosition* pNextStt = pFnd->Start();
2458 while( 0 < n )
2460 const SwRedline* pTmp = (*pRedlineTbl)[ --n ];
2461 if( pTmp->HasMark() && pTmp->IsVisible() )
2463 const SwPosition *pREnd;
2464 if( pFnd->GetType() == pTmp->GetType() &&
2465 pFnd->GetAuthor() == pTmp->GetAuthor() &&
2466 ( *pNextStt == *( pREnd = pTmp->End() ) ||
2467 IsPrevPos( *pREnd, *pNextStt )) )
2469 pNextStt = pTmp->Start();
2470 rSttPos = *pNextStt;
2472 else
2474 ++n;
2475 break;
2481 if( pFnd )
2483 const SwRedline* pSaveFnd = pFnd;
2485 SwCntntNode* pCNd;
2486 SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
2487 if( !pIdx->GetNode().IsCntntNode() &&
2488 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) )
2490 if( *pIdx >= rPam.GetPoint()->nNode )
2491 rPam.GetMark()->nContent.Assign( pCNd, pCNd->Len() );
2492 else
2493 pFnd = 0;
2496 if( pFnd )
2498 pIdx = &rPam.GetPoint()->nNode;
2499 if( !pIdx->GetNode().IsCntntNode() &&
2500 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) )
2502 if( *pIdx <= rPam.GetMark()->nNode )
2503 rPam.GetPoint()->nContent.Assign( pCNd, 0 );
2504 else
2505 pFnd = 0;
2509 if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
2511 if( n )
2513 bRestart = TRUE;
2514 *rPam.GetPoint() = *pSaveFnd->Start();
2516 else
2518 rPam.DeleteMark();
2519 *rPam.GetPoint() = aSavePos;
2521 pFnd = 0;
2524 } while( bRestart );
2526 return pFnd;
2529 // Kommentar am Redline setzen
2530 bool SwDoc::SetRedlineComment( const SwPaM& rPaM, const String& rS )
2532 BOOL bRet = FALSE;
2533 const SwPosition* pStt = rPaM.Start(),
2534 * pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
2535 : rPaM.GetPoint();
2536 USHORT n = 0;
2537 if( lcl_FindCurrRedline( *pStt, n, TRUE ) )
2539 for( ; n < pRedlineTbl->Count(); ++n )
2541 bRet = TRUE;
2542 SwRedline* pTmp = (*pRedlineTbl)[ n ];
2543 if( pStt != pEnd && *pTmp->Start() > *pEnd )
2544 break;
2546 pTmp->SetComment( rS );
2547 if( *pTmp->End() >= *pEnd )
2548 break;
2551 if( bRet )
2552 SetModified();
2554 return bRet;
2557 // legt gebenenfalls einen neuen Author an
2558 USHORT SwDoc::GetRedlineAuthor()
2560 return SW_MOD()->GetRedlineAuthor();
2563 // fuer die Reader usw. - neuen Author in die Tabelle eintragen
2564 USHORT SwDoc::InsertRedlineAuthor( const String& rNew )
2566 return SW_MOD()->InsertRedlineAuthor(rNew);
2569 void SwDoc::UpdateRedlineAttr()
2571 const SwRedlineTbl& rTbl = GetRedlineTbl();
2572 for( USHORT n = 0; n < rTbl.Count(); ++n )
2574 SwRedline* pRedl = rTbl[ n ];
2575 if( pRedl->IsVisible() )
2576 pRedl->InvalidateRange();
2580 // setze Kommentar-Text fuers Redline, das dann per AppendRedline
2581 // hereinkommt. Wird vom Autoformat benutzt. 0-Pointer setzt den Modus
2582 // wieder zurueck. Pointer wird nicht kopiert, muss also gueltig bleiben!
2583 void SwDoc::SetAutoFmtRedlineComment( const String* pTxt, USHORT nSeqNo )
2585 mbIsAutoFmtRedline = 0 != pTxt;
2586 if( pTxt )
2588 if( !pAutoFmtRedlnComment )
2589 pAutoFmtRedlnComment = new String( *pTxt );
2590 else
2591 *pAutoFmtRedlnComment = *pTxt;
2593 else if( pAutoFmtRedlnComment )
2594 delete pAutoFmtRedlnComment, pAutoFmtRedlnComment = 0;
2596 nAutoFmtRedlnCommentNo = nSeqNo;
2599 void SwDoc::SetRedlinePassword(
2600 /*[in]*/const uno::Sequence <sal_Int8>& rNewPassword)
2602 aRedlinePasswd = rNewPassword;
2603 SetModified();
2606 /* \f */
2608 BOOL SwRedlineTbl::Insert( SwRedlinePtr& p, BOOL bIns )
2610 BOOL bRet = FALSE;
2611 if( p->HasValidRange() )
2613 bRet = _SwRedlineTbl::Insert( p );
2614 p->CallDisplayFunc();
2616 else if( bIns )
2617 bRet = InsertWithValidRanges( p );
2618 else
2620 ASSERT( !this, "Redline: falscher Bereich" );
2622 return bRet;
2625 BOOL SwRedlineTbl::Insert( SwRedlinePtr& p, USHORT& rP, BOOL bIns )
2627 BOOL bRet = FALSE;
2628 if( p->HasValidRange() )
2630 bRet = _SwRedlineTbl::Insert( p, rP );
2631 p->CallDisplayFunc();
2633 else if( bIns )
2634 bRet = InsertWithValidRanges( p, &rP );
2635 else
2637 ASSERT( !this, "Redline: falscher Bereich" );
2639 return bRet;
2642 BOOL SwRedlineTbl::InsertWithValidRanges( SwRedlinePtr& p, USHORT* pInsPos )
2644 // erzeuge aus den Selektion gueltige "Teilbereiche".
2645 BOOL bAnyIns = FALSE;
2646 SwPosition* pStt = p->Start(),
2647 * pEnd = pStt == p->GetPoint() ? p->GetMark() : p->GetPoint();
2648 SwPosition aNewStt( *pStt );
2649 SwNodes& rNds = aNewStt.nNode.GetNodes();
2650 SwCntntNode* pC;
2652 if( !aNewStt.nNode.GetNode().IsCntntNode() )
2654 pC = rNds.GoNext( &aNewStt.nNode );
2655 if( pC )
2656 aNewStt.nContent.Assign( pC, 0 );
2657 else
2658 aNewStt.nNode = rNds.GetEndOfContent();
2661 SwRedline* pNew = 0;
2662 USHORT nInsPos;
2664 if( aNewStt < *pEnd )
2665 do {
2666 if( !pNew )
2667 pNew = new SwRedline( p->GetRedlineData(), aNewStt );
2668 else
2670 pNew->DeleteMark();
2671 *pNew->GetPoint() = aNewStt;
2674 pNew->SetMark();
2675 GoEndSection( pNew->GetPoint() );
2676 // i60396: If the redlines starts before a table but the table is the last member
2677 // of the section, the GoEndSection will end inside the table.
2678 // This will result in an incorrect redline, so we've to go back
2679 SwNode* pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode();
2680 // We end in a table when pTab != 0
2681 if( pTab && !pNew->GetMark()->nNode.GetNode().StartOfSectionNode()->FindTableNode() )
2682 { // but our Mark was outside the table => Correction
2685 // We want to be before the table
2686 *pNew->GetPoint() = SwPosition(*pTab);
2687 pC = GoPreviousNds( &pNew->GetPoint()->nNode, FALSE ); // here we are.
2688 if( pC )
2689 pNew->GetPoint()->nContent.Assign( pC, 0 );
2690 pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode();
2691 }while( pTab ); // If there is another table we have to repeat our step backwards
2694 if( *pNew->GetPoint() > *pEnd )
2696 pC = 0;
2697 if( aNewStt.nNode != pEnd->nNode )
2698 do {
2699 SwNode& rCurNd = aNewStt.nNode.GetNode();
2700 if( rCurNd.IsStartNode() )
2702 if( rCurNd.EndOfSectionIndex() < pEnd->nNode.GetIndex() )
2703 aNewStt.nNode = *rCurNd.EndOfSectionNode();
2704 else
2705 break;
2707 else if( rCurNd.IsCntntNode() )
2708 pC = rCurNd.GetCntntNode();
2709 aNewStt.nNode++;
2710 } while( aNewStt.nNode.GetIndex() < pEnd->nNode.GetIndex() );
2712 if( aNewStt.nNode == pEnd->nNode )
2713 aNewStt.nContent = pEnd->nContent;
2714 else if( pC )
2716 aNewStt.nNode = *pC;
2717 aNewStt.nContent.Assign( pC, pC->Len() );
2720 if( aNewStt <= *pEnd )
2721 *pNew->GetPoint() = aNewStt;
2723 else
2724 aNewStt = *pNew->GetPoint();
2725 #ifdef DEBUG
2726 CheckPosition( pNew->GetPoint(), pNew->GetMark() );
2727 #endif
2728 if( *pNew->GetPoint() != *pNew->GetMark() &&
2729 _SwRedlineTbl::Insert( pNew, nInsPos ) )
2731 pNew->CallDisplayFunc();
2732 bAnyIns = TRUE;
2733 pNew = 0;
2734 if( pInsPos && *pInsPos < nInsPos )
2735 *pInsPos = nInsPos;
2738 if( aNewStt >= *pEnd ||
2739 0 == (pC = rNds.GoNext( &aNewStt.nNode )) )
2740 break;
2742 aNewStt.nContent.Assign( pC, 0 );
2744 } while( aNewStt < *pEnd );
2746 delete pNew;
2747 delete p, p = 0;
2748 return bAnyIns;
2751 void SwRedlineTbl::Remove( USHORT nP, USHORT nL )
2753 SwDoc* pDoc = 0;
2754 if( !nP && nL && nL == _SwRedlineTbl::Count() )
2755 pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc();
2757 _SwRedlineTbl::Remove( nP, nL );
2759 ViewShell* pSh;
2760 if( pDoc && !pDoc->IsInDtor() && pDoc->GetRootFrm() &&
2761 0 != ( pSh = pDoc->GetRootFrm()->GetCurrShell()) )
2762 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
2765 void SwRedlineTbl::DeleteAndDestroy( USHORT nP, USHORT nL )
2767 SwDoc* pDoc = 0;
2768 if( !nP && nL && nL == _SwRedlineTbl::Count() )
2769 pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc();
2771 _SwRedlineTbl::DeleteAndDestroy( nP, nL );
2773 ViewShell* pSh;
2774 if( pDoc && !pDoc->IsInDtor() && pDoc->GetRootFrm() &&
2775 0 != ( pSh = pDoc->GetRootFrm()->GetCurrShell()) )
2776 pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
2779 // suche den naechsten oder vorherigen Redline mit dergleichen Seq.No
2780 // Mit dem Lookahead kann die Suche eingeschraenkt werden. 0 oder
2781 // USHRT_MAX suchen im gesamten Array.
2782 USHORT SwRedlineTbl::FindNextOfSeqNo( USHORT nSttPos, USHORT nLookahead ) const
2784 return nSttPos + 1 < _SwRedlineTbl::Count()
2785 ? FindNextSeqNo( _SwRedlineTbl::GetObject( nSttPos )
2786 ->GetSeqNo(), nSttPos+1, nLookahead )
2787 : USHRT_MAX;
2790 USHORT SwRedlineTbl::FindPrevOfSeqNo( USHORT nSttPos, USHORT nLookahead ) const
2792 return nSttPos ? FindPrevSeqNo( _SwRedlineTbl::GetObject(
2793 nSttPos )->GetSeqNo(),
2794 nSttPos-1, nLookahead )
2795 : USHRT_MAX;
2798 USHORT SwRedlineTbl::FindNextSeqNo( USHORT nSeqNo, USHORT nSttPos,
2799 USHORT nLookahead ) const
2801 USHORT nRet = USHRT_MAX, nEnd;
2802 if( nSeqNo && nSttPos < _SwRedlineTbl::Count() )
2804 nEnd = _SwRedlineTbl::Count();
2805 if( nLookahead && USHRT_MAX != nLookahead &&
2806 nSttPos + nLookahead < _SwRedlineTbl::Count() )
2807 nEnd = nSttPos + nLookahead;
2809 for( ; nSttPos < nEnd; ++nSttPos )
2810 if( nSeqNo == _SwRedlineTbl::GetObject( nSttPos )->GetSeqNo() )
2812 nRet = nSttPos;
2813 break;
2816 return nRet;
2819 USHORT SwRedlineTbl::FindPrevSeqNo( USHORT nSeqNo, USHORT nSttPos,
2820 USHORT nLookahead ) const
2822 USHORT nRet = USHRT_MAX, nEnd;
2823 if( nSeqNo && nSttPos < _SwRedlineTbl::Count() )
2825 nEnd = 0;
2826 if( nLookahead && USHRT_MAX != nLookahead && nSttPos > nLookahead )
2827 nEnd = nSttPos - nLookahead;
2829 ++nSttPos;
2830 while( nSttPos > nEnd )
2831 if( nSeqNo == _SwRedlineTbl::GetObject( --nSttPos )->GetSeqNo() )
2833 nRet = nSttPos;
2834 break;
2837 return nRet;
2840 /* \f */
2842 SwRedlineExtraData::~SwRedlineExtraData()
2846 void SwRedlineExtraData::Accept( SwPaM& ) const
2850 void SwRedlineExtraData::Reject( SwPaM& ) const
2854 int SwRedlineExtraData::operator == ( const SwRedlineExtraData& ) const
2856 return FALSE;
2860 SwRedlineExtraData_FmtColl::SwRedlineExtraData_FmtColl( const String& rColl,
2861 USHORT nPoolFmtId,
2862 const SfxItemSet* pItemSet )
2863 : sFmtNm(rColl), pSet(0), nPoolId(nPoolFmtId)
2865 if( pItemSet && pItemSet->Count() )
2866 pSet = new SfxItemSet( *pItemSet );
2869 SwRedlineExtraData_FmtColl::~SwRedlineExtraData_FmtColl()
2871 delete pSet;
2874 SwRedlineExtraData* SwRedlineExtraData_FmtColl::CreateNew() const
2876 return new SwRedlineExtraData_FmtColl( sFmtNm, nPoolId, pSet );
2879 void SwRedlineExtraData_FmtColl::Reject( SwPaM& rPam ) const
2881 SwDoc* pDoc = rPam.GetDoc();
2883 // was ist mit Undo ? ist das abgeschaltet ??
2884 SwTxtFmtColl* pColl = USHRT_MAX == nPoolId
2885 ? pDoc->FindTxtFmtCollByName( sFmtNm )
2886 : pDoc->GetTxtCollFromPool( nPoolId );
2887 if( pColl )
2888 pDoc->SetTxtFmtColl( rPam, pColl, false );
2890 if( pSet )
2892 rPam.SetMark();
2893 SwPosition& rMark = *rPam.GetMark();
2894 SwTxtNode* pTNd = rMark.nNode.GetNode().GetTxtNode();
2895 if( pTNd )
2897 rMark.nContent.Assign( pTNd, pTNd->GetTxt().Len() );
2899 if( pTNd->HasSwAttrSet() )
2901 // nur die setzen, die nicht mehr vorhanden sind. Andere
2902 // koennen jetzt veraendert drin stehen, aber die werden
2903 // nicht angefasst.
2904 SfxItemSet aTmp( *pSet );
2905 aTmp.Differentiate( *pTNd->GetpSwAttrSet() );
2906 pDoc->InsertItemSet( rPam, aTmp, 0 );
2908 else
2910 pDoc->InsertItemSet( rPam, *pSet, 0 );
2913 rPam.DeleteMark();
2917 int SwRedlineExtraData_FmtColl::operator == ( const SwRedlineExtraData& r) const
2919 const SwRedlineExtraData_FmtColl& rCmp = (SwRedlineExtraData_FmtColl&)r;
2920 return sFmtNm == rCmp.sFmtNm && nPoolId == rCmp.nPoolId &&
2921 ( ( !pSet && !rCmp.pSet ) ||
2922 ( pSet && rCmp.pSet && *pSet == *rCmp.pSet ) );
2925 void SwRedlineExtraData_FmtColl::SetItemSet( const SfxItemSet& rSet )
2927 delete pSet;
2928 if( rSet.Count() )
2929 pSet = new SfxItemSet( rSet );
2930 else
2931 pSet = 0;
2935 SwRedlineExtraData_Format::SwRedlineExtraData_Format( const SfxItemSet& rSet )
2937 SfxItemIter aIter( rSet );
2938 const SfxPoolItem* pItem = aIter.FirstItem();
2939 while( TRUE )
2941 aWhichIds.Insert( pItem->Which(), aWhichIds.Count() );
2942 if( aIter.IsAtEnd() )
2943 break;
2944 pItem = aIter.NextItem();
2948 SwRedlineExtraData_Format::SwRedlineExtraData_Format(
2949 const SwRedlineExtraData_Format& rCpy )
2950 : SwRedlineExtraData(), aWhichIds( (BYTE)rCpy.aWhichIds.Count() )
2952 aWhichIds.Insert( &rCpy.aWhichIds, 0 );
2955 SwRedlineExtraData_Format::~SwRedlineExtraData_Format()
2959 SwRedlineExtraData* SwRedlineExtraData_Format::CreateNew() const
2961 return new SwRedlineExtraData_Format( *this );
2964 void SwRedlineExtraData_Format::Reject( SwPaM& rPam ) const
2966 SwDoc* pDoc = rPam.GetDoc();
2968 RedlineMode_t eOld = pDoc->GetRedlineMode();
2969 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
2971 // eigentlich muesste hier das Attribut zurueck gesetzt werden!!!
2972 for( USHORT n = 0, nEnd = aWhichIds.Count(); n < nEnd; ++n )
2974 pDoc->InsertPoolItem( rPam, *GetDfltAttr( aWhichIds[ n ] ),
2975 nsSetAttrMode::SETATTR_DONTEXPAND );
2978 pDoc->SetRedlineMode_intern( eOld );
2981 int SwRedlineExtraData_Format::operator == ( const SwRedlineExtraData& rCmp ) const
2983 int nRet = 1;
2984 USHORT n = 0, nEnd = aWhichIds.Count();
2985 if( nEnd != ((SwRedlineExtraData_Format&)rCmp).aWhichIds.Count() )
2986 nRet = 0;
2987 else
2988 for( ; n < nEnd; ++n )
2989 if( ((SwRedlineExtraData_Format&)rCmp).aWhichIds[n] != aWhichIds[n])
2991 nRet = 0;
2992 break;
2994 return nRet;
2997 /* \f */
2999 SwRedlineData::SwRedlineData( RedlineType_t eT, USHORT nAut )
3000 : pNext( 0 ), pExtraData( 0 ), eType( eT ), nAuthor( nAut ), nSeqNo( 0 )
3002 aStamp.SetSec( 0 );
3003 aStamp.Set100Sec( 0 );
3006 SwRedlineData::SwRedlineData( const SwRedlineData& rCpy, BOOL bCpyNext )
3008 pNext( (bCpyNext && rCpy.pNext) ? new SwRedlineData( *rCpy.pNext ) : 0 ),
3009 pExtraData( rCpy.pExtraData ? rCpy.pExtraData->CreateNew() : 0 ),
3010 sComment( rCpy.sComment ), aStamp( rCpy.aStamp ), eType( rCpy.eType ),
3011 nAuthor( rCpy.nAuthor ), nSeqNo( rCpy.nSeqNo )
3015 // fuer sw3io: pNext geht in eigenen Besitz ueber!
3016 SwRedlineData::SwRedlineData(RedlineType_t eT, USHORT nAut, const DateTime& rDT,
3017 const String& rCmnt, SwRedlineData *pNxt, SwRedlineExtraData* pData)
3018 : pNext(pNxt), pExtraData(pData), sComment(rCmnt), aStamp(rDT),
3019 eType(eT), nAuthor(nAut), nSeqNo(0)
3023 SwRedlineData::~SwRedlineData()
3025 delete pExtraData;
3026 delete pNext;
3029 // ExtraData wird kopiert, der Pointer geht also NICHT in den Besitz
3030 // des RedlineObjectes!
3031 void SwRedlineData::SetExtraData( const SwRedlineExtraData* pData )
3033 delete pExtraData;
3035 if( pData )
3036 pExtraData = pData->CreateNew();
3037 else
3038 pExtraData = 0;
3041 // #111827#
3042 String SwRedlineData::GetDescr() const
3044 String aResult;
3046 aResult += String(SW_RES(STR_REDLINE_INSERT + GetType()));
3048 return aResult;
3051 /* \f */
3053 SwRedline::SwRedline(RedlineType_t eTyp, const SwPaM& rPam )
3054 : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ),
3055 pRedlineData( new SwRedlineData( eTyp, GetDoc()->GetRedlineAuthor() ) ),
3056 pCntntSect( 0 )
3058 bDelLastPara = bIsLastParaDelete = FALSE;
3059 bIsVisible = TRUE;
3060 if( !rPam.HasMark() )
3061 DeleteMark();
3064 SwRedline::SwRedline( const SwRedlineData& rData, const SwPaM& rPam )
3065 : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ),
3066 pRedlineData( new SwRedlineData( rData )),
3067 pCntntSect( 0 )
3069 bDelLastPara = bIsLastParaDelete = FALSE;
3070 bIsVisible = TRUE;
3071 if( !rPam.HasMark() )
3072 DeleteMark();
3075 SwRedline::SwRedline( const SwRedlineData& rData, const SwPosition& rPos )
3076 : SwPaM( rPos ),
3077 pRedlineData( new SwRedlineData( rData )),
3078 pCntntSect( 0 )
3080 bDelLastPara = bIsLastParaDelete = FALSE;
3081 bIsVisible = TRUE;
3084 SwRedline::SwRedline( const SwRedline& rCpy )
3085 : SwPaM( *rCpy.GetMark(), *rCpy.GetPoint() ),
3086 pRedlineData( new SwRedlineData( *rCpy.pRedlineData )),
3087 pCntntSect( 0 )
3089 bDelLastPara = bIsLastParaDelete = FALSE;
3090 bIsVisible = TRUE;
3091 if( !rCpy.HasMark() )
3092 DeleteMark();
3095 SwRedline::~SwRedline()
3097 if( pCntntSect )
3099 // dann den Content Bereich loeschen
3100 if( !GetDoc()->IsInDtor() )
3101 GetDoc()->DeleteSection( &pCntntSect->GetNode() );
3102 delete pCntntSect;
3104 delete pRedlineData;
3107 // liegt eine gueltige Selektion vor?
3108 BOOL SwRedline::HasValidRange() const
3110 const SwNode* pPtNd = &GetPoint()->nNode.GetNode(),
3111 * pMkNd = &GetMark()->nNode.GetNode();
3112 if( pPtNd->StartOfSectionNode() == pMkNd->StartOfSectionNode() &&
3113 !pPtNd->StartOfSectionNode()->IsTableNode() &&
3114 // JP 18.5.2001: Bug 87222 - invalid if points on the end of content
3115 // DVO 25.03.2002: #96530# end-of-content only invalid if no content
3116 // index exists
3117 ( pPtNd != pMkNd || GetContentIdx() != NULL ||
3118 pPtNd != &pPtNd->GetNodes().GetEndOfContent() )
3120 return TRUE;
3121 return FALSE;
3124 void SwRedline::CallDisplayFunc( USHORT nLoop )
3126 switch( nsRedlineMode_t::REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() )
3128 case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
3129 Show( nLoop );
3130 break;
3131 case nsRedlineMode_t::REDLINE_SHOW_INSERT:
3132 Hide( nLoop );
3133 break;
3134 case nsRedlineMode_t::REDLINE_SHOW_DELETE:
3135 ShowOriginal( nLoop );
3136 break;
3140 void SwRedline::Show( USHORT nLoop )
3142 if( 1 <= nLoop )
3144 SwDoc* pDoc = GetDoc();
3145 RedlineMode_t eOld = pDoc->GetRedlineMode();
3146 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
3147 BOOL bUndo = pDoc->DoesUndo();
3148 pDoc->DoUndo( FALSE );
3150 switch( GetType() )
3152 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
3153 bIsVisible = TRUE;
3154 MoveFromSection();
3155 break;
3157 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
3158 bIsVisible = TRUE;
3159 MoveFromSection();
3160 break;
3162 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
3163 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
3164 InvalidateRange();
3165 break;
3166 default:
3167 break;
3169 pDoc->SetRedlineMode_intern( eOld );
3170 pDoc->DoUndo( bUndo );
3174 void SwRedline::Hide( USHORT nLoop )
3176 SwDoc* pDoc = GetDoc();
3177 RedlineMode_t eOld = pDoc->GetRedlineMode();
3178 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
3179 BOOL bUndo = pDoc->DoesUndo();
3180 pDoc->DoUndo( FALSE );
3182 switch( GetType() )
3184 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
3185 bIsVisible = TRUE;
3186 if( 1 <= nLoop )
3187 MoveFromSection();
3188 break;
3190 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
3191 bIsVisible = FALSE;
3192 switch( nLoop )
3194 case 0: MoveToSection(); break;
3195 case 1: CopyToSection(); break;
3196 case 2: DelCopyOfSection(); break;
3198 break;
3200 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
3201 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
3202 if( 1 <= nLoop )
3203 InvalidateRange();
3204 break;
3205 default:
3206 break;
3208 pDoc->SetRedlineMode_intern( eOld );
3209 pDoc->DoUndo( bUndo );
3212 void SwRedline::ShowOriginal( USHORT nLoop )
3214 SwDoc* pDoc = GetDoc();
3215 RedlineMode_t eOld = pDoc->GetRedlineMode();
3216 SwRedlineData* pCur;
3218 pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
3219 BOOL bUndo = pDoc->DoesUndo();
3220 pDoc->DoUndo( FALSE );
3222 // bestimme den Type, ist der erste auf Stack
3223 for( pCur = pRedlineData; pCur->pNext; )
3224 pCur = pCur->pNext;
3226 switch( pCur->eType )
3228 case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
3229 bIsVisible = FALSE;
3230 switch( nLoop )
3232 case 0: MoveToSection(); break;
3233 case 1: CopyToSection(); break;
3234 case 2: DelCopyOfSection(); break;
3236 break;
3238 case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
3239 bIsVisible = TRUE;
3240 if( 1 <= nLoop )
3241 MoveFromSection();
3242 break;
3244 case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
3245 case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
3246 if( 1 <= nLoop )
3247 InvalidateRange();
3248 break;
3249 default:
3250 break;
3252 pDoc->SetRedlineMode_intern( eOld );
3253 pDoc->DoUndo( bUndo );
3257 void SwRedline::InvalidateRange() // das Layout anstossen
3259 ULONG nSttNd = GetMark()->nNode.GetIndex(),
3260 nEndNd = GetPoint()->nNode.GetIndex();
3261 USHORT nSttCnt = GetMark()->nContent.GetIndex(),
3262 nEndCnt = GetPoint()->nContent.GetIndex();
3264 if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
3266 ULONG nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
3267 nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (USHORT)nTmp;
3270 SwUpdateAttr aHt( 0, 0, RES_FMT_CHG );
3271 SwNodes& rNds = GetDoc()->GetNodes();
3272 SwNode* pNd;
3273 for( ULONG n = nSttNd; n <= nEndNd; ++n )
3274 if( ND_TEXTNODE == ( pNd = rNds[ n ] )->GetNodeType() )
3276 aHt.nStart = n == nSttNd ? nSttCnt : 0;
3277 aHt.nEnd = n == nEndNd ? nEndCnt : ((SwTxtNode*)pNd)->GetTxt().Len();
3278 ((SwTxtNode*)pNd)->Modify( &aHt, &aHt );
3282 /*************************************************************************
3283 * SwRedline::CalcStartEnd()
3284 * Calculates the start and end position of the intersection rTmp and
3285 * text node nNdIdx
3286 *************************************************************************/
3288 void SwRedline::CalcStartEnd( ULONG nNdIdx, USHORT& nStart, USHORT& nEnd ) const
3290 const SwPosition *pRStt = Start(), *pREnd = End();
3291 if( pRStt->nNode < nNdIdx )
3293 if( pREnd->nNode > nNdIdx )
3295 nStart = 0; // Absatz ist komplett enthalten
3296 nEnd = STRING_LEN;
3298 else
3300 ASSERT( pREnd->nNode == nNdIdx,
3301 "SwRedlineItr::Seek: GetRedlinePos Error" );
3302 nStart = 0; // Absatz wird vorne ueberlappt
3303 nEnd = pREnd->nContent.GetIndex();
3306 else if( pRStt->nNode == nNdIdx )
3308 nStart = pRStt->nContent.GetIndex();
3309 if( pREnd->nNode == nNdIdx )
3310 nEnd = pREnd->nContent.GetIndex(); // Innerhalb des Absatzes
3311 else
3312 nEnd = STRING_LEN; // Absatz wird hinten ueberlappt
3314 else
3316 nStart = STRING_LEN;
3317 nEnd = STRING_LEN;
3321 void SwRedline::MoveToSection()
3323 if( !pCntntSect )
3325 const SwPosition* pStt = Start(),
3326 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
3328 SwDoc* pDoc = GetDoc();
3329 SwPaM aPam( *pStt, *pEnd );
3330 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
3331 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
3333 if( !pCSttNd )
3335 // damit die Indizies der anderen Redlines nicht mitverschoben
3336 // werden, diese aufs Ende setzen (ist exclusive).
3337 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
3338 for( USHORT n = 0; n < rTbl.Count(); ++n )
3340 SwRedline* pRedl = rTbl[ n ];
3341 if( pRedl->GetBound(TRUE) == *pStt )
3342 pRedl->GetBound(TRUE) = *pEnd;
3343 if( pRedl->GetBound(FALSE) == *pStt )
3344 pRedl->GetBound(FALSE) = *pEnd;
3348 SwStartNode* pSttNd;
3349 SwNodes& rNds = pDoc->GetNodes();
3350 if( pCSttNd || pCEndNd )
3352 SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
3353 ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
3354 : (pCEndNd && pCEndNd->IsTxtNode() )
3355 ? ((SwTxtNode*)pCEndNd)->GetTxtColl()
3356 : pDoc->GetTxtCollFromPool(
3357 RES_POOLCOLL_STANDARD );
3359 pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
3360 SwNormalStartNode, pColl );
3361 SwTxtNode* pTxtNd = rNds[ pSttNd->GetIndex() + 1 ]->GetTxtNode();
3363 SwNodeIndex aNdIdx( *pTxtNd );
3364 SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
3365 if( pCSttNd && pCEndNd )
3366 pDoc->MoveAndJoin( aPam, aPos, IDocumentContentOperations::DOC_MOVEDEFAULT );
3367 else
3369 if( pCSttNd && !pCEndNd )
3370 bDelLastPara = TRUE;
3371 pDoc->MoveRange( aPam, aPos,
3372 IDocumentContentOperations::DOC_MOVEDEFAULT );
3375 else
3377 pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
3378 SwNormalStartNode );
3380 SwPosition aPos( *pSttNd->EndOfSectionNode() );
3381 pDoc->MoveRange( aPam, aPos,
3382 IDocumentContentOperations::DOC_MOVEDEFAULT );
3384 pCntntSect = new SwNodeIndex( *pSttNd );
3386 if( pStt == GetPoint() )
3387 Exchange();
3389 DeleteMark();
3391 else
3392 InvalidateRange();
3395 void SwRedline::CopyToSection()
3397 if( !pCntntSect )
3399 const SwPosition* pStt = Start(),
3400 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
3402 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
3403 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
3405 SwStartNode* pSttNd;
3406 SwDoc* pDoc = GetDoc();
3407 SwNodes& rNds = pDoc->GetNodes();
3409 BOOL bSaveCopyFlag = pDoc->IsCopyIsMove(),
3410 bSaveRdlMoveFlg = pDoc->IsRedlineMove();
3411 pDoc->SetCopyIsMove( TRUE );
3413 // #100619# The IsRedlineMove() flag causes the behaviour of the
3414 // SwDoc::_CopyFlyInFly method to change, which will eventually be
3415 // called by the pDoc->Copy line below (through SwDoc::_Copy,
3416 // SwDoc::CopyWithFlyInFly). This rather obscure bugfix was introduced
3417 // for #63198# and #64896#, and apparently never really worked.
3418 pDoc->SetRedlineMove( pStt->nContent == 0 );
3420 if( pCSttNd )
3422 SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
3423 ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
3424 : pDoc->GetTxtCollFromPool(
3425 RES_POOLCOLL_STANDARD );
3427 pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
3428 SwNormalStartNode, pColl );
3430 SwNodeIndex aNdIdx( *pSttNd, 1 );
3431 SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode();
3432 SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
3433 pDoc->CopyRange( *this, aPos, false );
3435 // JP 08.10.98: die Vorlage vom EndNode ggfs. mit uebernehmen
3436 // - ist im Doc::Copy nicht erwuenscht
3437 if( pCEndNd && pCEndNd != pCSttNd )
3439 SwCntntNode* pDestNd = aPos.nNode.GetNode().GetCntntNode();
3440 if( pDestNd )
3442 if( pDestNd->IsTxtNode() && pCEndNd->IsTxtNode() )
3443 ((SwTxtNode*)pCEndNd)->CopyCollFmt(
3444 *(SwTxtNode*)pDestNd );
3445 else
3446 pDestNd->ChgFmtColl( pCEndNd->GetFmtColl() );
3450 else
3452 pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
3453 SwNormalStartNode );
3455 if( pCEndNd )
3457 SwPosition aPos( *pSttNd->EndOfSectionNode() );
3458 pDoc->CopyRange( *this, aPos, false );
3460 else
3462 SwNodeIndex aInsPos( *pSttNd->EndOfSectionNode() );
3463 SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 );
3464 pDoc->CopyWithFlyInFly( aRg, 0, aInsPos );
3467 pCntntSect = new SwNodeIndex( *pSttNd );
3469 pDoc->SetCopyIsMove( bSaveCopyFlag );
3470 pDoc->SetRedlineMove( bSaveRdlMoveFlg );
3474 void SwRedline::DelCopyOfSection()
3476 if( pCntntSect )
3478 const SwPosition* pStt = Start(),
3479 * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
3481 SwDoc* pDoc = GetDoc();
3482 SwPaM aPam( *pStt, *pEnd );
3483 SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
3484 SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
3486 if( !pCSttNd )
3488 // damit die Indizies der anderen Redlines nicht mitverschoben
3489 // werden, diese aufs Ende setzen (ist exclusive).
3490 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
3491 for( USHORT n = 0; n < rTbl.Count(); ++n )
3493 SwRedline* pRedl = rTbl[ n ];
3494 if( pRedl->GetBound(TRUE) == *pStt )
3495 pRedl->GetBound(TRUE) = *pEnd;
3496 if( pRedl->GetBound(FALSE) == *pStt )
3497 pRedl->GetBound(FALSE) = *pEnd;
3501 if( pCSttNd && pCEndNd )
3503 // --> OD 2009-08-20 #i100466#
3504 // force a <join next> on <delete and join> operation
3505 pDoc->DeleteAndJoin( aPam, true );
3506 // <--
3508 else if( pCSttNd || pCEndNd )
3510 if( pCSttNd && !pCEndNd )
3511 bDelLastPara = TRUE;
3512 pDoc->DeleteRange( aPam );
3514 if( bDelLastPara )
3516 // #100611# To prevent dangling references to the paragraph to
3517 // be deleted, redline that point into this paragraph should be
3518 // moved to the new end position. Since redlines in the redline
3519 // table are sorted and the pEnd position is an endnode (see
3520 // bDelLastPara condition above), only redlines before the
3521 // current ones can be affected.
3522 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
3523 USHORT n = rTbl.GetPos( this );
3524 ASSERT( n != USHRT_MAX, "How strange. We don't exist!" );
3525 for( BOOL bBreak = FALSE; !bBreak && n > 0; )
3527 --n;
3528 bBreak = TRUE;
3529 if( rTbl[ n ]->GetBound(TRUE) == *aPam.GetPoint() )
3531 rTbl[ n ]->GetBound(TRUE) = *pEnd;
3532 bBreak = FALSE;
3534 if( rTbl[ n ]->GetBound(FALSE) == *aPam.GetPoint() )
3536 rTbl[ n ]->GetBound(FALSE) = *pEnd;
3537 bBreak = FALSE;
3541 SwPosition aEnd( *pEnd );
3542 *GetPoint() = *pEnd;
3543 *GetMark() = *pEnd;
3544 DeleteMark();
3546 aPam.GetBound( TRUE ).nContent.Assign( 0, 0 );
3547 aPam.GetBound( FALSE ).nContent.Assign( 0, 0 );
3548 aPam.DeleteMark();
3549 pDoc->DelFullPara( aPam );
3552 else
3554 pDoc->DeleteRange( aPam );
3557 if( pStt == GetPoint() )
3558 Exchange();
3560 DeleteMark();
3564 void SwRedline::MoveFromSection()
3566 if( pCntntSect )
3568 SwDoc* pDoc = GetDoc();
3569 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
3570 SvPtrarr aBeforeArr( 16, 16 ), aBehindArr( 16, 16 );
3571 USHORT nMyPos = rTbl.GetPos( this );
3572 ASSERT( this, "this nicht im Array?" );
3573 BOOL bBreak = FALSE;
3574 USHORT n;
3576 for( n = nMyPos+1; !bBreak && n < rTbl.Count(); ++n )
3578 bBreak = TRUE;
3579 if( rTbl[ n ]->GetBound(TRUE) == *GetPoint() )
3581 void* pTmp = &rTbl[ n ]->GetBound(TRUE);
3582 aBehindArr.Insert( pTmp, aBehindArr.Count());
3583 bBreak = FALSE;
3585 if( rTbl[ n ]->GetBound(FALSE) == *GetPoint() )
3587 void* pTmp = &rTbl[ n ]->GetBound(FALSE);
3588 aBehindArr.Insert( pTmp, aBehindArr.Count() );
3589 bBreak = FALSE;
3592 for( bBreak = FALSE, n = nMyPos; !bBreak && n ; )
3594 --n;
3595 bBreak = TRUE;
3596 if( rTbl[ n ]->GetBound(TRUE) == *GetPoint() )
3598 void* pTmp = &rTbl[ n ]->GetBound(TRUE);
3599 aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
3600 bBreak = FALSE;
3602 if( rTbl[ n ]->GetBound(FALSE) == *GetPoint() )
3604 void* pTmp = &rTbl[ n ]->GetBound(FALSE);
3605 aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
3606 bBreak = FALSE;
3610 // --> OD 2009-03-17 #i95711#
3611 const SwNode* pKeptCntntSectNode( &pCntntSect->GetNode() );
3612 // <--
3614 SwPaM aPam( pCntntSect->GetNode(),
3615 *pCntntSect->GetNode().EndOfSectionNode(), 1,
3616 ( bDelLastPara ? -2 : -1 ) );
3617 SwCntntNode* pCNd = aPam.GetCntntNode();
3618 if( pCNd )
3619 aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
3620 else
3621 aPam.GetPoint()->nNode++;
3623 SwFmtColl* pColl = pCNd && pCNd->Len() && aPam.GetPoint()->nNode !=
3624 aPam.GetMark()->nNode
3625 ? pCNd->GetFmtColl() : 0;
3627 SwNodeIndex aNdIdx( GetPoint()->nNode, -1 );
3628 USHORT nPos = GetPoint()->nContent.GetIndex();
3630 SwPosition aPos( *GetPoint() );
3631 if( bDelLastPara && *aPam.GetPoint() == *aPam.GetMark() )
3633 aPos.nNode--;
3635 pDoc->AppendTxtNode( aPos );
3637 else
3639 pDoc->MoveRange( aPam, aPos,
3640 IDocumentContentOperations::DOC_MOVEALLFLYS );
3643 SetMark();
3644 *GetPoint() = aPos;
3645 GetMark()->nNode = aNdIdx.GetIndex() + 1;
3646 pCNd = GetMark()->nNode.GetNode().GetCntntNode();
3647 GetMark()->nContent.Assign( pCNd, nPos );
3649 if( bDelLastPara )
3651 GetPoint()->nNode++;
3652 GetPoint()->nContent.Assign( pCNd = GetCntntNode(), 0 );
3653 bDelLastPara = FALSE;
3655 else if( pColl )
3656 pCNd = GetCntntNode();
3658 if( pColl && pCNd )
3659 pCNd->ChgFmtColl( pColl );
3661 // --> OD 2009-03-17 #i95771#
3662 // Under certain conditions the previous <SwDoc::Move(..)> has already
3663 // remove the change tracking section of this <SwRedline> instance from
3664 // the change tracking nodes area.
3665 // Thus, check, if <pCntntSect> still points to the change tracking section
3666 // by comparing it with the "indexed" <SwNode> instance copied before
3667 // perform the intrinsic move.
3668 // Note: Such condition is e.g. a "delete" change tracking only containing a table.
3669 if ( &pCntntSect->GetNode() == pKeptCntntSectNode )
3671 pDoc->DeleteSection( &pCntntSect->GetNode() );
3673 // <--
3674 delete pCntntSect, pCntntSect = 0;
3676 // #100611# adjustment of redline table positions must take start and
3677 // end into account, not point and mark.
3678 for( n = 0; n < aBeforeArr.Count(); ++n )
3679 *(SwPosition*)aBeforeArr[ n ] = *Start();
3680 for( n = 0; n < aBehindArr.Count(); ++n )
3681 *(SwPosition*)aBehindArr[ n ] = *End();
3683 else
3684 InvalidateRange();
3687 // fuers Undo
3688 void SwRedline::SetContentIdx( const SwNodeIndex* pIdx )
3690 if( pIdx && !pCntntSect )
3692 pCntntSect = new SwNodeIndex( *pIdx );
3693 bIsVisible = FALSE;
3695 else if( !pIdx && pCntntSect )
3697 delete pCntntSect, pCntntSect = 0;
3698 bIsVisible = FALSE;
3700 #ifndef PRODUCT
3701 else
3702 ASSERT( !this, "das ist keine gueltige Operation" );
3703 #endif
3706 BOOL SwRedline::CanCombine( const SwRedline& rRedl ) const
3708 return IsVisible() && rRedl.IsVisible() &&
3709 pRedlineData->CanCombine( *rRedl.pRedlineData );
3712 void SwRedline::PushData( const SwRedline& rRedl, BOOL bOwnAsNext )
3714 // SwRedlineData* pNew = new SwRedlineData( rRedl.GetType(),
3715 // rRedl.GetAuthor() );
3716 SwRedlineData* pNew = new SwRedlineData( *rRedl.pRedlineData, FALSE );
3717 if( bOwnAsNext )
3719 pNew->pNext = pRedlineData;
3720 pRedlineData = pNew;
3722 else
3724 pNew->pNext = pRedlineData->pNext;
3725 pRedlineData->pNext = pNew;
3729 BOOL SwRedline::PopData()
3731 if( !pRedlineData->pNext )
3732 return FALSE;
3733 SwRedlineData* pCur = pRedlineData;
3734 pRedlineData = pCur->pNext;
3735 pCur->pNext = 0;
3736 delete pCur;
3737 return TRUE;
3740 USHORT SwRedline::GetStackCount() const
3742 USHORT nRet = 1;
3743 for( SwRedlineData* pCur = pRedlineData; pCur->pNext; ++nRet )
3744 pCur = pCur->pNext;
3745 return nRet;
3748 // -> #111827#
3749 USHORT SwRedline::GetAuthor( USHORT nPos ) const
3751 return GetRedlineData(nPos).nAuthor;
3754 const String& SwRedline::GetAuthorString( USHORT nPos ) const
3756 return SW_MOD()->GetRedlineAuthor(GetRedlineData(nPos).nAuthor);
3759 const DateTime& SwRedline::GetTimeStamp( USHORT nPos ) const
3761 return GetRedlineData(nPos).aStamp;
3764 RedlineType_t SwRedline::GetRealType( USHORT nPos ) const
3766 return GetRedlineData(nPos).eType;
3769 const String& SwRedline::GetComment( USHORT nPos ) const
3771 return GetRedlineData(nPos).sComment;
3773 // <- #111827#
3775 int SwRedline::operator==( const SwRedline& rCmp ) const
3777 return this == &rCmp;
3780 int SwRedline::operator<( const SwRedline& rCmp ) const
3782 BOOL nResult = FALSE;
3784 if (*Start() < *rCmp.Start())
3785 nResult = TRUE;
3786 else if (*Start() == *rCmp.Start())
3787 if (*End() < *rCmp.End())
3788 nResult = TRUE;
3790 return nResult;
3793 // -> #111827#
3794 const SwRedlineData & SwRedline::GetRedlineData(USHORT nPos) const
3796 SwRedlineData * pCur = pRedlineData;
3798 while (nPos > 0 && NULL != pCur->pNext)
3800 pCur = pCur->pNext;
3802 nPos--;
3805 ASSERT( 0 == nPos, "Pos angabe ist zu gross" );
3807 return *pCur;
3810 String SwRedline::GetDescr(USHORT nPos)
3812 String aResult;
3814 // get description of redline data (e.g.: "insert $1")
3815 aResult = GetRedlineData(nPos).GetDescr();
3817 SwPaM * pPaM = NULL;
3818 bool bDeletePaM = false;
3820 // if this redline is visible the content is in this PaM
3821 if (NULL == pCntntSect)
3823 pPaM = this;
3825 else // otherwise it is saved in pCntntSect
3827 SwNodeIndex aTmpIdx( *pCntntSect->GetNode().EndOfSectionNode() );
3828 pPaM = new SwPaM(*pCntntSect, aTmpIdx );
3829 bDeletePaM = true;
3832 // replace $1 in description by description of the redlines text
3833 String aTmpStr;
3834 aTmpStr += String(SW_RES(STR_START_QUOTE));
3835 aTmpStr += ShortenString(pPaM->GetTxt(), nUndoStringLength,
3836 String(SW_RES(STR_LDOTS)));
3837 aTmpStr += String(SW_RES(STR_END_QUOTE));
3839 SwRewriter aRewriter;
3840 aRewriter.AddRule(UNDO_ARG1, aTmpStr);
3842 aResult = aRewriter.Apply(aResult);
3844 if (bDeletePaM)
3845 delete pPaM;
3847 return aResult;
3849 // <- #111827#
3852 bool SwDoc::IsInRedlines(const SwNode & rNode) const
3854 SwPosition aPos(rNode);
3855 SwNode & rEndOfRedlines = aNodes.GetEndOfRedlines();
3856 SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()),
3857 SwPosition(rEndOfRedlines));
3859 return aPam.ContainsPosition(aPos) ? sal_True : sal_False;