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>
40 #include <sfx2/app.hxx>
41 #include <svx/colritem.hxx>
42 #include <svx/udlnitem.hxx>
43 #include <svx/crsditem.hxx>
44 #include <swmodule.hxx>
48 #include <redline.hxx>
52 #include <poolfmt.hxx>
54 #include <rootfrm.hxx>
56 #include <comcore.hrc>
58 using namespace com::sun::star
;
60 TYPEINIT1(SwRedlineHint
, SfxHint
);
64 #define _CHECK_REDLINE( pDoc )
65 #define _DEBUG_REDLINE( pDoc )
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" );
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
)
148 const SwRedline
* pCurrent
= rTbl
[ n
];
149 const SwRedline
* pNext
= n
+1 < rTbl
.Count() ? rTbl
[ n
+1 ] : 0;
150 if( pCurrent
== pNext
)
153 ++nDummy
; // Possible debugger breakpoint
157 #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
161 SV_IMPL_OP_PTRARR_SORT( _SwRedlineTbl
, SwRedlinePtr
)
163 RedlineMode_t
SwDoc::GetRedlineMode() const
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
;
185 case nsRedlineMode_t::REDLINE_SHOW_INSERT
:
186 pFnc
= &SwRedline::Hide
;
188 case nsRedlineMode_t::REDLINE_SHOW_DELETE
:
189 pFnc
= &SwRedline::ShowOriginal
;
193 pFnc
= &SwRedline::Hide
;
194 eMode
= (RedlineMode_t
)(eMode
| nsRedlineMode_t::REDLINE_SHOW_INSERT
);
198 _CHECK_REDLINE( this )
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
;
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
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()
258 bool CheckPosition( const SwPosition
* pStt
, const SwPosition
* pEnd
)
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
)
275 if( !pSttTab
&& pSttStart
!= pEndStart
)
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
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
305 - Ueberlappung von Text und - Redline Object einfuegen, der
306 anderem Insert andere Insert wird vom Delete
310 bool SwDoc::AppendRedline( SwRedline
* pNewRedl
, bool bCallDelete
)
313 SwRedline
aCopy( *pNewRedl
);
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" );
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" );
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
378 BOOL bCompress
= FALSE
;
380 // zur StartPos das erste Redline suchen
381 if( !GetRedline( *pStt
, &n
) && n
)
385 for( ; pNewRedl
&& n
< pRedlineTbl
->Count(); bDec
? n
: ++n
)
389 _CHECK_REDLINE( this )
392 SwRedline
* pRedl
= (*pRedlineTbl
)[ n
];
393 SwPosition
* pRStt
= pRedl
->Start(),
394 * pREnd
= pRStt
== pRedl
->GetPoint() ? pRedl
->GetMark()
397 // #i8518# remove empty redlines while we're at it
398 if( ( *pRStt
== *pREnd
) &&
399 ( pRedl
->GetContentIdx() == NULL
) )
401 pRedlineTbl
->DeleteAndDestroy(n
);
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() )
431 pRedlineTbl
->Remove( n
);
432 pRedlineTbl
->Insert( pRedl
);
438 else if( (( POS_BEFORE
== eCmpPos
&&
439 IsPrevPos( *pEnd
, *pRStt
) ) ||
440 ( POS_COLLIDE_END
== eCmpPos
) ||
441 ( POS_OVERLAP_BEFORE
== eCmpPos
) ) &&
442 pRedl
->CanCombine( *pNewRedl
) &&
444 *(*pRedlineTbl
)[ n
-1 ]->End() != *pRStt
))
446 pRedl
->SetStart( *pStt
, pRStt
);
448 pRedlineTbl
->Remove( n
);
449 pRedlineTbl
->Insert( pRedl
);
454 else if ( POS_OUTSIDE
== eCmpPos
)
456 // #107164# own insert-over-insert
457 // redlines: just scrap the inside ones
458 pRedlineTbl
->Remove( n
);
462 else if( POS_OVERLAP_BEHIND
== eCmpPos
)
465 if( ( *pStt
== *pEnd
) &&
466 ( pNewRedl
->GetContentIdx() == NULL
) )
469 else if( POS_OVERLAP_BEFORE
== eCmpPos
)
472 if( ( *pStt
== *pEnd
) &&
473 ( pNewRedl
->GetContentIdx() == NULL
) )
476 else if( POS_INSIDE
== eCmpPos
|| POS_EQUAL
== eCmpPos
)
481 delete pNewRedl
, pNewRedl
= 0;
485 else if( POS_INSIDE
== eCmpPos
)
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
);
501 else if( !pRedl
->HasValidRange() )
504 pRedlineTbl
->Remove( n
);
505 pRedlineTbl
->Insert( pRedl
);
508 else if ( POS_OUTSIDE
== eCmpPos
)
510 // #102366# handle overlapping redlines in broken
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
)
527 else if ( POS_OVERLAP_BEHIND
== eCmpPos
)
529 // #107164# handle overlapping redlines in broken
531 pNewRedl
->SetStart( *pREnd
);
533 else if ( POS_OVERLAP_BEFORE
== eCmpPos
)
535 // #107164# handle overlapping redlines in broken
538 if( ( *pStt
== *pEnd
) &&
539 ( pNewRedl
->GetContentIdx() == NULL
) )
547 case nsRedlineType_t::REDLINE_DELETE
:
548 if( POS_INSIDE
== eCmpPos
)
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
);
564 else if( !pRedl
->HasValidRange() )
567 pRedlineTbl
->Remove( n
);
568 pRedlineTbl
->Insert( pRedl
, n
);
571 else if ( POS_OUTSIDE
== eCmpPos
)
573 // #102366# handle overlapping redlines in broken
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
)
590 else if ( POS_EQUAL
== eCmpPos
)
592 // #112895# handle identical redlines in broken
593 // documents - delete old (delete) redline
594 pRedlineTbl
->DeleteAndDestroy( n
);
597 else if ( POS_OVERLAP_BEHIND
== eCmpPos
)
598 { // Another workaround for broken redlines (#107164#)
599 pNewRedl
->SetStart( *pREnd
);
602 case nsRedlineType_t::REDLINE_FORMAT
:
605 case POS_OVERLAP_BEFORE
:
606 pRedl
->SetStart( *pEnd
, pRStt
);
608 pRedlineTbl
->Remove( n
);
609 pRedlineTbl
->Insert( pRedl
, n
);
613 case POS_OVERLAP_BEHIND
:
614 pRedl
->SetEnd( *pStt
, pREnd
);
615 if( *pStt
== *pRStt
&& pRedl
->GetContentIdx() == NULL
)
617 pRedlineTbl
->DeleteAndDestroy( n
);
624 // ueberlappt den akt. komplett oder hat gleiche
625 // Ausdehung, dann muss der alte geloescht werden
626 pRedlineTbl
->DeleteAndDestroy( n
);
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
648 pRedl
->SetEnd( *pStt
, pREnd
);
659 case nsRedlineType_t::REDLINE_DELETE
:
660 switch( pRedl
->GetType() )
662 case nsRedlineType_t::REDLINE_DELETE
:
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
679 pNewRedl
->SetEnd( *pRStt
, pEnd
);
685 delete pNewRedl
, pNewRedl
= 0;
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
);
700 pNewRedl
->SetEnd( *pREnd
, pEnd
);
701 pRedlineTbl
->DeleteAndDestroy( n
);
704 else if( POS_OVERLAP_BEHIND
== eCmpPos
)
705 pNewRedl
->SetStart( *pREnd
, pStt
);
707 pNewRedl
->SetEnd( *pRStt
, pEnd
);
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
);
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
);
735 pNewRedl
->SetEnd( *pREnd
, pEnd
);
737 // delete current (below), and restart process with
739 USHORT nToBeDeleted
= n
;
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
757 pRedlineTbl
->DeleteAndDestroy( nToBeDeleted
);
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
));
781 pRedlineTbl
->DeleteAndDestroy( n
);
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() )
800 pEnd
->nContent
.Assign(
801 pEnd
->nNode
.GetNode().GetTxtNode(), 0);
802 DelFullPara( *pNewRedl
);
805 DeleteAndJoin( *pNewRedl
);
809 delete pNewRedl
, pNewRedl
= 0;
814 pRedlineTbl
->Remove( n
);
816 // damit pNew auch beim Verschieben der Indizies
817 // behandelt wird, erstmal temp. einfuegen
820 pRedlineTbl
->SavePtrInArr( pNewRedl
);
821 DeleteAndJoin( *pRedl
);
822 USHORT nFnd
= pRedlineTbl
->GetPos(pNewRedl
);
823 if( USHRT_MAX
!= nFnd
)
824 pRedlineTbl
->Remove( nFnd
);
832 case POS_OVERLAP_BEFORE
:
834 SwPaM
aPam( *pRStt
, *pEnd
);
836 if( *pEnd
== *pREnd
)
837 pRedlineTbl
->DeleteAndDestroy( n
);
840 pRedl
->SetStart( *pEnd
, pRStt
);
842 pRedlineTbl
->Remove( n
);
843 pRedlineTbl
->Insert( pRedl
, n
);
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
);
857 n
= 0; // neu Aufsetzen
863 case POS_OVERLAP_BEHIND
:
865 SwPaM
aPam( *pStt
, *pREnd
);
867 if( *pStt
== *pRStt
)
869 pRedlineTbl
->DeleteAndDestroy( n
);
873 pRedl
->SetEnd( *pStt
, pREnd
);
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
);
886 n
= 0; // neu Aufsetzen
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
909 pRedl
->PushData( *pNewRedl
);
910 delete pNewRedl
, pNewRedl
= 0;
911 if( IsHideChanges( eRedlineMode
))
919 pNewRedl
->PushData( *pRedl
, FALSE
);
920 if( *pRStt
== *pStt
)
922 pRedl
->SetStart( *pEnd
, pRStt
);
924 pRedlineTbl
->Remove( n
);
925 pRedlineTbl
->Insert( pRedl
, n
);
930 if( *pREnd
!= *pEnd
)
932 pNew
= new SwRedline( *pRedl
);
933 pNew
->SetStart( *pEnd
);
935 pRedl
->SetEnd( *pStt
, pREnd
);
936 if( !pRedl
->HasValidRange() )
939 pRedlineTbl
->Remove( n
);
940 pRedlineTbl
->Insert( pRedl
, n
);
948 pRedl
->PushData( *pNewRedl
);
949 if( *pEnd
== *pREnd
)
950 pNewRedl
->SetEnd( *pRStt
, pEnd
);
953 pNew
= new SwRedline( *pNewRedl
);
954 pNew
->SetEnd( *pRStt
);
955 pNewRedl
->SetStart( *pREnd
, pStt
);
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
);
972 pRedlineTbl
->GetPos(pNewRedl
));
977 pNew
= new SwRedline( *pRedl
);
978 pNew
->PushData( *pNewRedl
);
979 pNew
->SetEnd( *pEnd
);
980 pNewRedl
->SetEnd( *pRStt
, pEnd
);
981 pRedl
->SetStart( *pNew
->End(), pRStt
) ;
983 pRedlineTbl
->Remove( n
);
984 pRedlineTbl
->Insert( pRedl
);
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
);
1000 pRedlineTbl
->Remove(
1001 pRedlineTbl
->GetPos(pNewRedl
));
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() )
1014 pRedlineTbl
->Remove( n
);
1015 pRedlineTbl
->Insert( pRedl
);
1024 // insert the pNew part (if it exists)
1027 // AppendRedline( pNew, bCallDelete );
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)
1044 case nsRedlineType_t::REDLINE_FORMAT
:
1047 case POS_OVERLAP_BEFORE
:
1048 pRedl
->SetStart( *pEnd
, pRStt
);
1050 pRedlineTbl
->Remove( n
);
1051 pRedlineTbl
->Insert( pRedl
, n
);
1055 case POS_OVERLAP_BEHIND
:
1056 pRedl
->SetEnd( *pStt
, pREnd
);
1061 // ueberlappt den akt. komplett oder hat gleiche
1062 // Ausdehung, dann muss der alte geloescht werden
1063 pRedlineTbl
->DeleteAndDestroy( n
);
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
1086 pRedl
->SetEnd( *pStt
, pREnd
);
1097 case nsRedlineType_t::REDLINE_FORMAT
:
1098 switch( pRedl
->GetType() )
1100 case nsRedlineType_t::REDLINE_INSERT
:
1101 case nsRedlineType_t::REDLINE_DELETE
:
1104 case POS_OVERLAP_BEFORE
:
1105 pNewRedl
->SetEnd( *pRStt
, pEnd
);
1108 case POS_OVERLAP_BEHIND
:
1109 pNewRedl
->SetStart( *pREnd
, pStt
);
1114 // TODO Check if there is any side effect
1115 //delete pNewRedl, pNewRedl = 0;
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
1134 pNewRedl
->SetEnd( *pRStt
, pEnd
);
1140 case nsRedlineType_t::REDLINE_FORMAT
:
1146 // ueberlappt den akt. komplett oder hat gleiche
1147 // Ausdehnung, dann muss der alte geloescht werden
1148 pRedlineTbl
->DeleteAndDestroy( n
);
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
);
1167 pRedlineTbl
->Remove( n
);
1168 pRedlineTbl
->Insert( pRedl
, n
);
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
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
);
1194 pNewRedl
->SetEnd( *pREnd
, pEnd
);
1195 pRedlineTbl
->DeleteAndDestroy( n
);
1198 else if( POS_OVERLAP_BEHIND
== eCmpPos
)
1199 pNewRedl
->SetStart( *pREnd
, pStt
);
1201 pNewRedl
->SetEnd( *pRStt
, pEnd
);
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
);
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
);
1239 case nsRedlineType_t::REDLINE_FMTCOLL
:
1240 // wie soll das verhalten sein????
1241 // erstmal so einfuegen
1250 if( ( *pStt
== *pEnd
) &&
1251 ( pNewRedl
->GetContentIdx() == NULL
) )
1252 { // Do not insert empty redlines
1257 pRedlineTbl
->Insert( pNewRedl
);
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
;
1291 case nsRedlineMode_t::REDLINE_SHOW_INSERT
:
1292 pFnc
= &SwRedline::Hide
;
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
1316 pPrev
->SetEnd( *pCur
->End() );
1317 pRedlineTbl
->DeleteAndDestroy( n
);
1323 _CHECK_REDLINE( this )
1326 bool SwDoc::SplitRedline( const SwPaM
& rRange
)
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()
1340 if( *pTStt
<= *pStt
&& *pStt
<= *pTEnd
&&
1341 *pTStt
<= *pEnd
&& *pEnd
<= *pTEnd
)
1345 if( *pStt
== *pTStt
)
1347 if( *pEnd
== *pTEnd
)
1350 SwRedline
* pNew
= 0;
1354 pNew
= new SwRedline( *pTmp
);
1355 pTmp
->SetEnd( *pStt
, pTEnd
);
1356 pNew
->SetStart( *pEnd
);
1368 pTmp
->InvalidateRange();
1369 pRedlineTbl
->DeleteAndDestroy( n
-- );
1373 if( pTmp
&& !pTmp
->HasValidRange() )
1376 pRedlineTbl
->Remove( n
);
1377 pRedlineTbl
->Insert( pTmp
, n
);
1380 pRedlineTbl
->Insert( pNew
, n
);
1382 else if( *pEnd
< *pTStt
)
1388 bool SwDoc::DeleteRedline( const SwPaM
& rRange
, bool bSaveInUndo
,
1391 if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES
& eRedlineMode
||
1392 !rRange
.HasMark() || *rRange
.GetMark() == *rRange
.GetPoint() )
1397 if( bSaveInUndo
&& DoesUndo() )
1399 SwUndoRedline
* pUndo
= new SwUndoRedline( UNDO_REDLINE
, rRange
);
1400 if( pUndo
->GetRedlSaveCount() )
1403 AppendUndo( pUndo
);
1409 const SwPosition
* pStt
= rRange
.Start(),
1410 * pEnd
= pStt
== rRange
.GetPoint() ? rRange
.GetMark()
1411 : rRange
.GetPoint();
1413 GetRedline( *pStt
, &n
);
1414 for( ; n
< pRedlineTbl
->Count() ; ++n
)
1416 SwRedline
* pRedl
= (*pRedlineTbl
)[ n
];
1417 if( USHRT_MAX
!= nDelType
&& nDelType
!= pRedl
->GetType() )
1420 SwPosition
* pRStt
= pRedl
->Start(),
1421 * pREnd
= pRStt
== pRedl
->GetPoint() ? pRedl
->GetMark()
1422 : pRedl
->GetPoint();
1424 switch( ComparePosition( *pStt
, *pEnd
, *pRStt
, *pREnd
) )
1431 case POS_OVERLAP_BEFORE
:
1432 if( *pEnd
== *pREnd
)
1436 pRedl
->InvalidateRange();
1437 pRedl
->SetStart( *pEnd
, pRStt
);
1439 pRedlineTbl
->Remove( n
);
1440 pRedlineTbl
->Insert( pRedl
);
1445 case POS_OVERLAP_BEHIND
:
1446 if( *pStt
== *pRStt
)
1450 pRedl
->InvalidateRange();
1451 pRedl
->SetEnd( *pStt
, pREnd
);
1452 if( !pRedl
->HasValidRange() )
1455 pRedlineTbl
->Remove( n
);
1456 pRedlineTbl
->Insert( pRedl
);
1464 // der muss gesplittet werden
1465 pRedl
->InvalidateRange();
1466 if( *pRStt
== *pStt
)
1468 pRedl
->SetStart( *pEnd
, pRStt
);
1470 pRedlineTbl
->Remove( n
);
1471 pRedlineTbl
->Insert( pRedl
);
1477 if( *pREnd
!= *pEnd
)
1479 pCpy
= new SwRedline( *pRedl
);
1480 pCpy
->SetStart( *pEnd
);
1484 pRedl
->SetEnd( *pStt
, pREnd
);
1485 if( !pRedl
->HasValidRange() )
1488 pRedlineTbl
->Remove( pRedlineTbl
->GetPos( pRedl
));
1489 pRedlineTbl
->Insert( pRedl
);
1493 pRedlineTbl
->Insert( pCpy
);
1498 case POS_COLLIDE_END
:
1500 n
= pRedlineTbl
->Count();
1508 pRedl
->InvalidateRange();
1509 pRedlineTbl
->DeleteAndDestroy( n
-- );
1520 bool SwDoc::DeleteRedline( const SwStartNode
& rNode
, bool bSaveInUndo
,
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
)
1547 const SwRedline
* SwDoc::GetRedline( const SwPosition
& rPos
,
1548 USHORT
* pFndPos
) const
1550 USHORT nO
= pRedlineTbl
->Count(), nM
, nU
= 0;
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()
1561 : pRedl
->GetPoint();
1564 : ( *pStt
<= rPos
&& rPos
< *pEnd
) )
1566 /* #107318# returned wrong redline ???*/
1567 while( nM
&& rPos
== *(*pRedlineTbl
)[ nM
- 1 ]->End() &&
1568 rPos
== *(*pRedlineTbl
)[ nM
- 1 ]->Start() )
1571 pRedl
= (*pRedlineTbl
)[ nM
];
1578 else if( *pEnd
<= rPos
)
1595 typedef BOOL (*Fn_AcceptReject
)( SwRedlineTbl
& rArr
, USHORT
& rPos
,
1597 const SwPosition
* pSttRng
,
1598 const SwPosition
* pEndRng
);
1600 BOOL
lcl_AcceptRedline( SwRedlineTbl
& rArr
, USHORT
& rPos
,
1602 const SwPosition
* pSttRng
= 0,
1603 const SwPosition
* pEndRng
= 0 )
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
;
1627 if( *pSttRng
== *pRStt
)
1628 pRedl
->SetStart( *pEndRng
, pRStt
);
1631 if( *pEndRng
!= *pREnd
)
1634 SwRedline
* pNew
= new SwRedline( *pRedl
);
1635 pNew
->SetStart( *pEndRng
);
1636 rArr
.Insert( pNew
); ++rPos
;
1638 pRedl
->SetEnd( *pSttRng
, pREnd
);
1643 case POS_OVERLAP_BEFORE
:
1644 pRedl
->SetStart( *pEndRng
, pRStt
);
1648 case POS_OVERLAP_BEHIND
:
1649 pRedl
->SetEnd( *pSttRng
, pREnd
);
1655 rArr
.DeleteAndDestroy( rPos
-- );
1662 if( bReplace
|| ( bCheck
&& !pRedl
->HasValidRange() ))
1665 rArr
.Remove( rArr
.GetPos( pRedl
));
1666 rArr
.Insert( pRedl
);
1670 case nsRedlineType_t::REDLINE_DELETE
:
1672 SwDoc
& rDoc
= *pRedl
->GetDoc();
1673 const SwPosition
*pDelStt
= 0, *pDelEnd
= 0;
1674 BOOL bDelRedl
= FALSE
;
1685 case POS_OVERLAP_BEFORE
:
1692 case POS_OVERLAP_BEHIND
:
1703 rArr
.Remove( rPos
-- );
1707 pDelStt
= pRedl
->Start();
1708 pDelEnd
= pRedl
->End();
1716 if( pDelStt
&& pDelEnd
)
1718 SwPaM
aPam( *pDelStt
, *pDelEnd
);
1719 SwCntntNode
* pCSttNd
= pDelStt
->nNode
.GetNode().GetCntntNode();
1720 SwCntntNode
* pCEndNd
= pDelEnd
->nNode
.GetNode().GetCntntNode();
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
);
1732 rDoc
.DeleteRange( aPam
);
1734 if( pCSttNd
&& !pCEndNd
)
1736 aPam
.GetBound( TRUE
).nContent
.Assign( 0, 0 );
1737 aPam
.GetBound( FALSE
).nContent
.Assign( 0, 0 );
1739 rDoc
.DelFullPara( aPam
);
1742 rDoc
.SetRedlineMode_intern( eOld
);
1749 case nsRedlineType_t::REDLINE_FMTCOLL
:
1750 rArr
.DeleteAndDestroy( rPos
-- );
1759 BOOL
lcl_RejectRedline( SwRedlineTbl
& rArr
, USHORT
& rPos
,
1761 const SwPosition
* pSttRng
= 0,
1762 const SwPosition
* pEndRng
= 0 )
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
;
1794 case POS_OVERLAP_BEFORE
:
1801 case POS_OVERLAP_BEHIND
:
1811 // dann den Bereich wieder loeschen
1812 rArr
.Remove( rPos
-- );
1816 pDelStt
= pRedl
->Start();
1817 pDelEnd
= pRedl
->End();
1825 if( pDelStt
&& pDelEnd
)
1827 SwPaM
aPam( *pDelStt
, *pDelEnd
);
1829 SwCntntNode
* pCSttNd
= pDelStt
->nNode
.GetNode().GetCntntNode();
1830 SwCntntNode
* pCEndNd
= pDelEnd
->nNode
.GetNode().GetCntntNode();
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
);
1842 rDoc
.DeleteRange( aPam
);
1844 if( pCSttNd
&& !pCEndNd
)
1846 aPam
.GetBound( TRUE
).nContent
.Assign( 0, 0 );
1847 aPam
.GetBound( FALSE
).nContent
.Assign( 0, 0 );
1849 rDoc
.DelFullPara( aPam
);
1852 rDoc
.SetRedlineMode_intern( eOld
);
1858 case nsRedlineType_t::REDLINE_DELETE
:
1860 SwRedline
* pNew
= 0;
1861 BOOL bCheck
= FALSE
, bReplace
= FALSE
;
1867 if( 1 < pRedl
->GetStackCount() )
1869 pNew
= new SwRedline( *pRedl
);
1872 if( *pSttRng
== *pRStt
)
1874 pRedl
->SetStart( *pEndRng
, pRStt
);
1877 pNew
->SetEnd( *pEndRng
);
1881 if( *pEndRng
!= *pREnd
)
1884 SwRedline
* pCpy
= new SwRedline( *pRedl
);
1885 pCpy
->SetStart( *pEndRng
);
1886 rArr
.Insert( pCpy
); ++rPos
;
1888 pNew
->SetEnd( *pEndRng
);
1891 pRedl
->SetEnd( *pSttRng
, pREnd
);
1894 pNew
->SetStart( *pSttRng
);
1899 case POS_OVERLAP_BEFORE
:
1900 if( 1 < pRedl
->GetStackCount() )
1902 pNew
= new SwRedline( *pRedl
);
1905 pRedl
->SetStart( *pEndRng
, pRStt
);
1908 pNew
->SetEnd( *pEndRng
);
1911 case POS_OVERLAP_BEHIND
:
1912 if( 1 < pRedl
->GetStackCount() )
1914 pNew
= new SwRedline( *pRedl
);
1917 pRedl
->SetEnd( *pSttRng
, pREnd
);
1920 pNew
->SetStart( *pSttRng
);
1925 if( !pRedl
->PopData() )
1926 // das RedlineObject loeschen reicht
1927 rArr
.DeleteAndDestroy( rPos
-- );
1936 rArr
.Insert( pNew
); ++rPos
;
1939 if( bReplace
|| ( bCheck
&& !pRedl
->HasValidRange() ))
1942 rArr
.Remove( rArr
.GetPos( pRedl
));
1943 rArr
.Insert( pRedl
);
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
-- );
1964 const SwRedline
* lcl_FindCurrRedline( const SwPosition
& rSttPos
,
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()
1978 if( bNext
? *pRStt
<= rSttPos
: *pRStt
< rSttPos
)
1980 if( bNext
? *pREnd
> rSttPos
: *pREnd
>= rSttPos
)
1994 int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject
,
1995 SwRedlineTbl
& rArr
, BOOL bCallDelete
,
1999 int nCount
= 0; // #111827#
2001 const SwPosition
* pStt
= rPam
.Start(),
2002 * pEnd
= pStt
== rPam
.GetPoint() ? rPam
.GetMark()
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#
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#
2026 if( *pTmp
->Start() < *pEnd
)
2028 // dann nur in der TeilSelektion aufheben
2029 if( (*fn_AcceptReject
)( rArr
, n
, bCallDelete
, pStt
, pEnd
))
2030 nCount
++; // #111827#
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()
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 );
2054 const SwPosition
* pRStt
= pRedl
->Start();
2055 if( !pRStt
->nContent
.GetIndex() && pRStt
->nNode
.GetIndex() ==
2056 pStt
->nNode
.GetIndex() - 1 )
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 );
2067 const SwPosition
* pREnd
= pRedl
->End();
2068 if( !pREnd
->nContent
.GetIndex() && pREnd
->nNode
.GetIndex() ==
2069 pEnd
->nNode
.GetIndex() + 1 )
2076 bool SwDoc::AcceptRedline( USHORT nPos
, bool bCallDelete
)
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() )
2091 SwRewriter aRewriter
;
2093 aRewriter
.AddRule(UNDO_ARG1
, pTmp
->GetDescr());
2094 StartUndo( UNDO_ACCEPT_REDLINE
, &aRewriter
);
2098 USHORT nSeqNo
= pTmp
->GetSeqNo();
2103 AppendUndo( new SwUndoAcceptRedline( *pTmp
));
2105 bRet
|= lcl_AcceptRedline( *pRedlineTbl
, nPos
, bCallDelete
);
2109 if( USHRT_MAX
== nPos
)
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
];
2124 } while( nLoopCnt
);
2133 EndUndo( UNDO_ACCEPT_REDLINE
, NULL
);
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
);
2153 StartUndo( UNDO_ACCEPT_REDLINE
, NULL
);
2154 AppendUndo( new SwUndoAcceptRedline( aPam
));
2158 int nRet
= lcl_AcceptRejectRedl( lcl_AcceptRedline
, *pRedlineTbl
,
2159 bCallDelete
, aPam
);
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
);
2184 bool SwDoc::RejectRedline( USHORT nPos
, bool bCallDelete
)
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() )
2199 SwRewriter aRewriter
;
2201 aRewriter
.AddRule(UNDO_ARG1
, pTmp
->GetDescr());
2202 StartUndo( UNDO_REJECT_REDLINE
, NULL
);
2206 USHORT nSeqNo
= pTmp
->GetSeqNo();
2211 AppendUndo( new SwUndoRejectRedline( *pTmp
));
2213 bRet
|= lcl_RejectRedline( *pRedlineTbl
, nPos
, bCallDelete
);
2217 if( USHRT_MAX
== nPos
)
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
];
2232 } while( nLoopCnt
);
2241 EndUndo( UNDO_REJECT_REDLINE
, NULL
);
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
);
2261 StartUndo( UNDO_REJECT_REDLINE
, NULL
);
2262 AppendUndo( new SwUndoRejectRedline( aPam
));
2266 int nRet
= lcl_AcceptRejectRedl( lcl_RejectRedline
, *pRedlineTbl
,
2267 bCallDelete
, aPam
);
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
);
2293 const SwRedline
* SwDoc::SelNextRedline( SwPaM
& rPam
) const
2298 SwPosition
& rSttPos
= *rPam
.GetPoint();
2299 SwPosition
aSavePos( rSttPos
);
2302 // sollte die StartPos auf dem letzen gueligen ContentNode stehen,
2303 // dann aufjedenfall das naechste Redline nehmen
2305 const SwRedline
* pFnd
= lcl_FindCurrRedline( rSttPos
, n
, TRUE
);
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() ))
2318 rSttPos
= *pFnd
->End();
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();
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
;
2364 const SwRedline
* pSaveFnd
= pFnd
;
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 );
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() );
2390 if( !pFnd
|| *rPam
.GetMark() == *rPam
.GetPoint() )
2392 if( n
< pRedlineTbl
->Count() )
2395 *rPam
.GetPoint() = *pSaveFnd
->End();
2400 *rPam
.GetPoint() = aSavePos
;
2405 } while( bRestart
);
2410 const SwRedline
* SwDoc::SelPrevRedline( SwPaM
& rPam
) const
2415 SwPosition
& rSttPos
= *rPam
.GetPoint();
2416 SwPosition
aSavePos( rSttPos
);
2419 // sollte die StartPos auf dem ersten gueligen ContentNode stehen,
2420 // dann aufjedenfall das vorherige Redline nehmen
2422 const SwRedline
* pFnd
= lcl_FindCurrRedline( rSttPos
, n
, FALSE
);
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() ))
2435 rSttPos
= *pFnd
->Start();
2441 while( !pFnd
&& 0 < n
)
2443 pFnd
= (*pRedlineTbl
)[ --n
];
2444 if( pFnd
->HasMark() && pFnd
->IsVisible() )
2446 *rPam
.GetMark() = *pFnd
->End();
2447 rSttPos
= *pFnd
->Start();
2455 // alle vom gleichen Typ und Author, die hinter einander liegen
2456 // zu einer Selektion zusammenfassen.
2457 const SwPosition
* pNextStt
= pFnd
->Start();
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
;
2483 const SwRedline
* pSaveFnd
= pFnd
;
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() );
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 );
2509 if( !pFnd
|| *rPam
.GetMark() == *rPam
.GetPoint() )
2514 *rPam
.GetPoint() = *pSaveFnd
->Start();
2519 *rPam
.GetPoint() = aSavePos
;
2524 } while( bRestart
);
2529 // Kommentar am Redline setzen
2530 bool SwDoc::SetRedlineComment( const SwPaM
& rPaM
, const String
& rS
)
2533 const SwPosition
* pStt
= rPaM
.Start(),
2534 * pEnd
= pStt
== rPaM
.GetPoint() ? rPaM
.GetMark()
2537 if( lcl_FindCurrRedline( *pStt
, n
, TRUE
) )
2539 for( ; n
< pRedlineTbl
->Count(); ++n
)
2542 SwRedline
* pTmp
= (*pRedlineTbl
)[ n
];
2543 if( pStt
!= pEnd
&& *pTmp
->Start() > *pEnd
)
2546 pTmp
->SetComment( rS
);
2547 if( *pTmp
->End() >= *pEnd
)
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
;
2588 if( !pAutoFmtRedlnComment
)
2589 pAutoFmtRedlnComment
= new String( *pTxt
);
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
;
2608 BOOL
SwRedlineTbl::Insert( SwRedlinePtr
& p
, BOOL bIns
)
2611 if( p
->HasValidRange() )
2613 bRet
= _SwRedlineTbl::Insert( p
);
2614 p
->CallDisplayFunc();
2617 bRet
= InsertWithValidRanges( p
);
2620 ASSERT( !this, "Redline: falscher Bereich" );
2625 BOOL
SwRedlineTbl::Insert( SwRedlinePtr
& p
, USHORT
& rP
, BOOL bIns
)
2628 if( p
->HasValidRange() )
2630 bRet
= _SwRedlineTbl::Insert( p
, rP
);
2631 p
->CallDisplayFunc();
2634 bRet
= InsertWithValidRanges( p
, &rP
);
2637 ASSERT( !this, "Redline: falscher Bereich" );
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();
2652 if( !aNewStt
.nNode
.GetNode().IsCntntNode() )
2654 pC
= rNds
.GoNext( &aNewStt
.nNode
);
2656 aNewStt
.nContent
.Assign( pC
, 0 );
2658 aNewStt
.nNode
= rNds
.GetEndOfContent();
2661 SwRedline
* pNew
= 0;
2664 if( aNewStt
< *pEnd
)
2667 pNew
= new SwRedline( p
->GetRedlineData(), aNewStt
);
2671 *pNew
->GetPoint() = aNewStt
;
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.
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
)
2697 if( aNewStt
.nNode
!= pEnd
->nNode
)
2699 SwNode
& rCurNd
= aNewStt
.nNode
.GetNode();
2700 if( rCurNd
.IsStartNode() )
2702 if( rCurNd
.EndOfSectionIndex() < pEnd
->nNode
.GetIndex() )
2703 aNewStt
.nNode
= *rCurNd
.EndOfSectionNode();
2707 else if( rCurNd
.IsCntntNode() )
2708 pC
= rCurNd
.GetCntntNode();
2710 } while( aNewStt
.nNode
.GetIndex() < pEnd
->nNode
.GetIndex() );
2712 if( aNewStt
.nNode
== pEnd
->nNode
)
2713 aNewStt
.nContent
= pEnd
->nContent
;
2716 aNewStt
.nNode
= *pC
;
2717 aNewStt
.nContent
.Assign( pC
, pC
->Len() );
2720 if( aNewStt
<= *pEnd
)
2721 *pNew
->GetPoint() = aNewStt
;
2724 aNewStt
= *pNew
->GetPoint();
2726 CheckPosition( pNew
->GetPoint(), pNew
->GetMark() );
2728 if( *pNew
->GetPoint() != *pNew
->GetMark() &&
2729 _SwRedlineTbl::Insert( pNew
, nInsPos
) )
2731 pNew
->CallDisplayFunc();
2734 if( pInsPos
&& *pInsPos
< nInsPos
)
2738 if( aNewStt
>= *pEnd
||
2739 0 == (pC
= rNds
.GoNext( &aNewStt
.nNode
)) )
2742 aNewStt
.nContent
.Assign( pC
, 0 );
2744 } while( aNewStt
< *pEnd
);
2751 void SwRedlineTbl::Remove( USHORT nP
, USHORT nL
)
2754 if( !nP
&& nL
&& nL
== _SwRedlineTbl::Count() )
2755 pDoc
= _SwRedlineTbl::GetObject( 0 )->GetDoc();
2757 _SwRedlineTbl::Remove( nP
, nL
);
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
)
2768 if( !nP
&& nL
&& nL
== _SwRedlineTbl::Count() )
2769 pDoc
= _SwRedlineTbl::GetObject( 0 )->GetDoc();
2771 _SwRedlineTbl::DeleteAndDestroy( nP
, nL
);
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
)
2790 USHORT
SwRedlineTbl::FindPrevOfSeqNo( USHORT nSttPos
, USHORT nLookahead
) const
2792 return nSttPos
? FindPrevSeqNo( _SwRedlineTbl::GetObject(
2793 nSttPos
)->GetSeqNo(),
2794 nSttPos
-1, nLookahead
)
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() )
2819 USHORT
SwRedlineTbl::FindPrevSeqNo( USHORT nSeqNo
, USHORT nSttPos
,
2820 USHORT nLookahead
) const
2822 USHORT nRet
= USHRT_MAX
, nEnd
;
2823 if( nSeqNo
&& nSttPos
< _SwRedlineTbl::Count() )
2826 if( nLookahead
&& USHRT_MAX
!= nLookahead
&& nSttPos
> nLookahead
)
2827 nEnd
= nSttPos
- nLookahead
;
2830 while( nSttPos
> nEnd
)
2831 if( nSeqNo
== _SwRedlineTbl::GetObject( --nSttPos
)->GetSeqNo() )
2842 SwRedlineExtraData::~SwRedlineExtraData()
2846 void SwRedlineExtraData::Accept( SwPaM
& ) const
2850 void SwRedlineExtraData::Reject( SwPaM
& ) const
2854 int SwRedlineExtraData::operator == ( const SwRedlineExtraData
& ) const
2860 SwRedlineExtraData_FmtColl::SwRedlineExtraData_FmtColl( const String
& rColl
,
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()
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
);
2888 pDoc
->SetTxtFmtColl( rPam
, pColl
, false );
2893 SwPosition
& rMark
= *rPam
.GetMark();
2894 SwTxtNode
* pTNd
= rMark
.nNode
.GetNode().GetTxtNode();
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
2904 SfxItemSet
aTmp( *pSet
);
2905 aTmp
.Differentiate( *pTNd
->GetpSwAttrSet() );
2906 pDoc
->InsertItemSet( rPam
, aTmp
, 0 );
2910 pDoc
->InsertItemSet( rPam
, *pSet
, 0 );
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
)
2929 pSet
= new SfxItemSet( rSet
);
2935 SwRedlineExtraData_Format::SwRedlineExtraData_Format( const SfxItemSet
& rSet
)
2937 SfxItemIter
aIter( rSet
);
2938 const SfxPoolItem
* pItem
= aIter
.FirstItem();
2941 aWhichIds
.Insert( pItem
->Which(), aWhichIds
.Count() );
2942 if( aIter
.IsAtEnd() )
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
2984 USHORT n
= 0, nEnd
= aWhichIds
.Count();
2985 if( nEnd
!= ((SwRedlineExtraData_Format
&)rCmp
).aWhichIds
.Count() )
2988 for( ; n
< nEnd
; ++n
)
2989 if( ((SwRedlineExtraData_Format
&)rCmp
).aWhichIds
[n
] != aWhichIds
[n
])
2999 SwRedlineData::SwRedlineData( RedlineType_t eT
, USHORT nAut
)
3000 : pNext( 0 ), pExtraData( 0 ), eType( eT
), nAuthor( nAut
), nSeqNo( 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()
3029 // ExtraData wird kopiert, der Pointer geht also NICHT in den Besitz
3030 // des RedlineObjectes!
3031 void SwRedlineData::SetExtraData( const SwRedlineExtraData
* pData
)
3036 pExtraData
= pData
->CreateNew();
3042 String
SwRedlineData::GetDescr() const
3046 aResult
+= String(SW_RES(STR_REDLINE_INSERT
+ GetType()));
3053 SwRedline::SwRedline(RedlineType_t eTyp
, const SwPaM
& rPam
)
3054 : SwPaM( *rPam
.GetMark(), *rPam
.GetPoint() ),
3055 pRedlineData( new SwRedlineData( eTyp
, GetDoc()->GetRedlineAuthor() ) ),
3058 bDelLastPara
= bIsLastParaDelete
= FALSE
;
3060 if( !rPam
.HasMark() )
3064 SwRedline::SwRedline( const SwRedlineData
& rData
, const SwPaM
& rPam
)
3065 : SwPaM( *rPam
.GetMark(), *rPam
.GetPoint() ),
3066 pRedlineData( new SwRedlineData( rData
)),
3069 bDelLastPara
= bIsLastParaDelete
= FALSE
;
3071 if( !rPam
.HasMark() )
3075 SwRedline::SwRedline( const SwRedlineData
& rData
, const SwPosition
& rPos
)
3077 pRedlineData( new SwRedlineData( rData
)),
3080 bDelLastPara
= bIsLastParaDelete
= FALSE
;
3084 SwRedline::SwRedline( const SwRedline
& rCpy
)
3085 : SwPaM( *rCpy
.GetMark(), *rCpy
.GetPoint() ),
3086 pRedlineData( new SwRedlineData( *rCpy
.pRedlineData
)),
3089 bDelLastPara
= bIsLastParaDelete
= FALSE
;
3091 if( !rCpy
.HasMark() )
3095 SwRedline::~SwRedline()
3099 // dann den Content Bereich loeschen
3100 if( !GetDoc()->IsInDtor() )
3101 GetDoc()->DeleteSection( &pCntntSect
->GetNode() );
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
3117 ( pPtNd
!= pMkNd
|| GetContentIdx() != NULL
||
3118 pPtNd
!= &pPtNd
->GetNodes().GetEndOfContent() )
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
:
3131 case nsRedlineMode_t::REDLINE_SHOW_INSERT
:
3134 case nsRedlineMode_t::REDLINE_SHOW_DELETE
:
3135 ShowOriginal( nLoop
);
3140 void SwRedline::Show( USHORT 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
);
3152 case nsRedlineType_t::REDLINE_INSERT
: // Inhalt wurde eingefuegt
3157 case nsRedlineType_t::REDLINE_DELETE
: // Inhalt wurde geloescht
3162 case nsRedlineType_t::REDLINE_FORMAT
: // Attributierung wurde angewendet
3163 case nsRedlineType_t::REDLINE_TABLE
: // TabellenStruktur wurde veraendert
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
);
3184 case nsRedlineType_t::REDLINE_INSERT
: // Inhalt wurde eingefuegt
3190 case nsRedlineType_t::REDLINE_DELETE
: // Inhalt wurde geloescht
3194 case 0: MoveToSection(); break;
3195 case 1: CopyToSection(); break;
3196 case 2: DelCopyOfSection(); break;
3200 case nsRedlineType_t::REDLINE_FORMAT
: // Attributierung wurde angewendet
3201 case nsRedlineType_t::REDLINE_TABLE
: // TabellenStruktur wurde veraendert
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
; )
3226 switch( pCur
->eType
)
3228 case nsRedlineType_t::REDLINE_INSERT
: // Inhalt wurde eingefuegt
3232 case 0: MoveToSection(); break;
3233 case 1: CopyToSection(); break;
3234 case 2: DelCopyOfSection(); break;
3238 case nsRedlineType_t::REDLINE_DELETE
: // Inhalt wurde geloescht
3244 case nsRedlineType_t::REDLINE_FORMAT
: // Attributierung wurde angewendet
3245 case nsRedlineType_t::REDLINE_TABLE
: // TabellenStruktur wurde veraendert
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();
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
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
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
3312 nEnd
= STRING_LEN
; // Absatz wird hinten ueberlappt
3316 nStart
= STRING_LEN
;
3321 void SwRedline::MoveToSection()
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();
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
);
3369 if( pCSttNd
&& !pCEndNd
)
3370 bDelLastPara
= TRUE
;
3371 pDoc
->MoveRange( aPam
, aPos
,
3372 IDocumentContentOperations::DOC_MOVEDEFAULT
);
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() )
3395 void SwRedline::CopyToSection()
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 );
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();
3442 if( pDestNd
->IsTxtNode() && pCEndNd
->IsTxtNode() )
3443 ((SwTxtNode
*)pCEndNd
)->CopyCollFmt(
3444 *(SwTxtNode
*)pDestNd
);
3446 pDestNd
->ChgFmtColl( pCEndNd
->GetFmtColl() );
3452 pSttNd
= rNds
.MakeEmptySection( SwNodeIndex( rNds
.GetEndOfRedlines() ),
3453 SwNormalStartNode
);
3457 SwPosition
aPos( *pSttNd
->EndOfSectionNode() );
3458 pDoc
->CopyRange( *this, aPos
, false );
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()
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();
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 );
3508 else if( pCSttNd
|| pCEndNd
)
3510 if( pCSttNd
&& !pCEndNd
)
3511 bDelLastPara
= TRUE
;
3512 pDoc
->DeleteRange( aPam
);
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; )
3529 if( rTbl
[ n
]->GetBound(TRUE
) == *aPam
.GetPoint() )
3531 rTbl
[ n
]->GetBound(TRUE
) = *pEnd
;
3534 if( rTbl
[ n
]->GetBound(FALSE
) == *aPam
.GetPoint() )
3536 rTbl
[ n
]->GetBound(FALSE
) = *pEnd
;
3541 SwPosition
aEnd( *pEnd
);
3542 *GetPoint() = *pEnd
;
3546 aPam
.GetBound( TRUE
).nContent
.Assign( 0, 0 );
3547 aPam
.GetBound( FALSE
).nContent
.Assign( 0, 0 );
3549 pDoc
->DelFullPara( aPam
);
3554 pDoc
->DeleteRange( aPam
);
3557 if( pStt
== GetPoint() )
3564 void SwRedline::MoveFromSection()
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
;
3576 for( n
= nMyPos
+1; !bBreak
&& n
< rTbl
.Count(); ++n
)
3579 if( rTbl
[ n
]->GetBound(TRUE
) == *GetPoint() )
3581 void* pTmp
= &rTbl
[ n
]->GetBound(TRUE
);
3582 aBehindArr
.Insert( pTmp
, aBehindArr
.Count());
3585 if( rTbl
[ n
]->GetBound(FALSE
) == *GetPoint() )
3587 void* pTmp
= &rTbl
[ n
]->GetBound(FALSE
);
3588 aBehindArr
.Insert( pTmp
, aBehindArr
.Count() );
3592 for( bBreak
= FALSE
, n
= nMyPos
; !bBreak
&& n
; )
3596 if( rTbl
[ n
]->GetBound(TRUE
) == *GetPoint() )
3598 void* pTmp
= &rTbl
[ n
]->GetBound(TRUE
);
3599 aBeforeArr
.Insert( pTmp
, aBeforeArr
.Count() );
3602 if( rTbl
[ n
]->GetBound(FALSE
) == *GetPoint() )
3604 void* pTmp
= &rTbl
[ n
]->GetBound(FALSE
);
3605 aBeforeArr
.Insert( pTmp
, aBeforeArr
.Count() );
3610 // --> OD 2009-03-17 #i95711#
3611 const SwNode
* pKeptCntntSectNode( &pCntntSect
->GetNode() );
3614 SwPaM
aPam( pCntntSect
->GetNode(),
3615 *pCntntSect
->GetNode().EndOfSectionNode(), 1,
3616 ( bDelLastPara
? -2 : -1 ) );
3617 SwCntntNode
* pCNd
= aPam
.GetCntntNode();
3619 aPam
.GetPoint()->nContent
.Assign( pCNd
, pCNd
->Len() );
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() )
3635 pDoc
->AppendTxtNode( aPos
);
3639 pDoc
->MoveRange( aPam
, aPos
,
3640 IDocumentContentOperations::DOC_MOVEALLFLYS
);
3645 GetMark()->nNode
= aNdIdx
.GetIndex() + 1;
3646 pCNd
= GetMark()->nNode
.GetNode().GetCntntNode();
3647 GetMark()->nContent
.Assign( pCNd
, nPos
);
3651 GetPoint()->nNode
++;
3652 GetPoint()->nContent
.Assign( pCNd
= GetCntntNode(), 0 );
3653 bDelLastPara
= FALSE
;
3656 pCNd
= GetCntntNode();
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() );
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();
3688 void SwRedline::SetContentIdx( const SwNodeIndex
* pIdx
)
3690 if( pIdx
&& !pCntntSect
)
3692 pCntntSect
= new SwNodeIndex( *pIdx
);
3695 else if( !pIdx
&& pCntntSect
)
3697 delete pCntntSect
, pCntntSect
= 0;
3702 ASSERT( !this, "das ist keine gueltige Operation" );
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
);
3719 pNew
->pNext
= pRedlineData
;
3720 pRedlineData
= pNew
;
3724 pNew
->pNext
= pRedlineData
->pNext
;
3725 pRedlineData
->pNext
= pNew
;
3729 BOOL
SwRedline::PopData()
3731 if( !pRedlineData
->pNext
)
3733 SwRedlineData
* pCur
= pRedlineData
;
3734 pRedlineData
= pCur
->pNext
;
3740 USHORT
SwRedline::GetStackCount() const
3743 for( SwRedlineData
* pCur
= pRedlineData
; pCur
->pNext
; ++nRet
)
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
;
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())
3786 else if (*Start() == *rCmp
.Start())
3787 if (*End() < *rCmp
.End())
3794 const SwRedlineData
& SwRedline::GetRedlineData(USHORT nPos
) const
3796 SwRedlineData
* pCur
= pRedlineData
;
3798 while (nPos
> 0 && NULL
!= pCur
->pNext
)
3805 ASSERT( 0 == nPos
, "Pos angabe ist zu gross" );
3810 String
SwRedline::GetDescr(USHORT nPos
)
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
)
3825 else // otherwise it is saved in pCntntSect
3827 SwNodeIndex
aTmpIdx( *pCntntSect
->GetNode().EndOfSectionNode() );
3828 pPaM
= new SwPaM(*pCntntSect
, aTmpIdx
);
3832 // replace $1 in description by description of the redlines text
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
);
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
;