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