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