xref: /AOO41X/main/sw/source/core/doc/docredln.cxx (revision 641de097e2e45da05c7073f6a714e738b4e22abb)
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( !this, "Redline: falscher Bereich" );
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( !this, "Redline: falscher Bereich" );
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     SwUpdateAttr aHt( 0, 0, RES_FMT_CHG );
3279     SwNodes& rNds = GetDoc()->GetNodes();
3280     SwNode* pNd;
3281     for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
3282         if( ND_TEXTNODE == ( pNd = rNds[ n ] )->GetNodeType() )
3283         {
3284             aHt.nStart = n == nSttNd ? nSttCnt : 0;
3285             aHt.nEnd = n == nEndNd ? nEndCnt : ((SwTxtNode*)pNd)->GetTxt().Len();
3286             ((SwTxtNode*)pNd)->ModifyNotification( &aHt, &aHt );
3287         }
3288 }
3289 
3290 /*************************************************************************
3291  *                      SwRedline::CalcStartEnd()
3292  * Calculates the start and end position of the intersection rTmp and
3293  * text node nNdIdx
3294  *************************************************************************/
3295 
CalcStartEnd(sal_uLong nNdIdx,sal_uInt16 & nStart,sal_uInt16 & nEnd) const3296 void SwRedline::CalcStartEnd( sal_uLong nNdIdx, sal_uInt16& nStart, sal_uInt16& nEnd ) const
3297 {
3298     const SwPosition *pRStt = Start(), *pREnd = End();
3299     if( pRStt->nNode < nNdIdx )
3300     {
3301         if( pREnd->nNode > nNdIdx )
3302         {
3303             nStart = 0;             // Absatz ist komplett enthalten
3304             nEnd = STRING_LEN;
3305         }
3306         else
3307         {
3308             ASSERT( pREnd->nNode == nNdIdx,
3309                 "SwRedlineItr::Seek: GetRedlinePos Error" );
3310             nStart = 0;             // Absatz wird vorne ueberlappt
3311             nEnd = pREnd->nContent.GetIndex();
3312         }
3313     }
3314     else if( pRStt->nNode == nNdIdx )
3315     {
3316         nStart = pRStt->nContent.GetIndex();
3317         if( pREnd->nNode == nNdIdx )
3318             nEnd = pREnd->nContent.GetIndex(); // Innerhalb des Absatzes
3319         else
3320             nEnd = STRING_LEN;      // Absatz wird hinten ueberlappt
3321     }
3322     else
3323     {
3324         nStart = STRING_LEN;
3325         nEnd = STRING_LEN;
3326     }
3327 }
3328 
MoveToSection()3329 void SwRedline::MoveToSection()
3330 {
3331     if( !pCntntSect )
3332     {
3333         const SwPosition* pStt = Start(),
3334                         * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
3335 
3336         SwDoc* pDoc = GetDoc();
3337         SwPaM aPam( *pStt, *pEnd );
3338         SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
3339         SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
3340 
3341         if( !pCSttNd )
3342         {
3343             // damit die Indizies der anderen Redlines nicht mitverschoben
3344             // werden, diese aufs Ende setzen (ist exclusive).
3345             const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
3346             for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
3347             {
3348                 SwRedline* pRedl = rTbl[ n ];
3349                 if( pRedl->GetBound(sal_True) == *pStt )
3350                     pRedl->GetBound(sal_True) = *pEnd;
3351                 if( pRedl->GetBound(sal_False) == *pStt )
3352                     pRedl->GetBound(sal_False) = *pEnd;
3353             }
3354         }
3355 
3356         SwStartNode* pSttNd;
3357         SwNodes& rNds = pDoc->GetNodes();
3358         if( pCSttNd || pCEndNd )
3359         {
3360             SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
3361                                     ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
3362                                     : (pCEndNd && pCEndNd->IsTxtNode() )
3363                                         ? ((SwTxtNode*)pCEndNd)->GetTxtColl()
3364                                         : pDoc->GetTxtCollFromPool(
3365                                                 RES_POOLCOLL_STANDARD );
3366 
3367             pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
3368                                             SwNormalStartNode, pColl );
3369             SwTxtNode* pTxtNd = rNds[ pSttNd->GetIndex() + 1 ]->GetTxtNode();
3370 
3371             SwNodeIndex aNdIdx( *pTxtNd );
3372             SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
3373             if( pCSttNd && pCEndNd )
3374                 pDoc->MoveAndJoin( aPam, aPos, IDocumentContentOperations::DOC_MOVEDEFAULT );
3375             else
3376             {
3377                 if( pCSttNd && !pCEndNd )
3378                     bDelLastPara = sal_True;
3379                 pDoc->MoveRange( aPam, aPos,
3380                     IDocumentContentOperations::DOC_MOVEDEFAULT );
3381             }
3382         }
3383         else
3384         {
3385             pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
3386                                             SwNormalStartNode );
3387 
3388             SwPosition aPos( *pSttNd->EndOfSectionNode() );
3389             pDoc->MoveRange( aPam, aPos,
3390                 IDocumentContentOperations::DOC_MOVEDEFAULT );
3391         }
3392         pCntntSect = new SwNodeIndex( *pSttNd );
3393 
3394         if( pStt == GetPoint() )
3395             Exchange();
3396 
3397         DeleteMark();
3398     }
3399     else
3400         InvalidateRange();
3401 }
3402 
CopyToSection()3403 void SwRedline::CopyToSection()
3404 {
3405     if( !pCntntSect )
3406     {
3407         const SwPosition* pStt = Start(),
3408                         * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
3409 
3410         SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
3411         SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
3412 
3413         SwStartNode* pSttNd;
3414         SwDoc* pDoc = GetDoc();
3415         SwNodes& rNds = pDoc->GetNodes();
3416 
3417         sal_Bool bSaveCopyFlag = pDoc->IsCopyIsMove(),
3418              bSaveRdlMoveFlg = pDoc->IsRedlineMove();
3419         pDoc->SetCopyIsMove( sal_True );
3420 
3421         // #100619# The IsRedlineMove() flag causes the behaviour of the
3422         // SwDoc::_CopyFlyInFly method to change, which will eventually be
3423         // called by the pDoc->Copy line below (through SwDoc::_Copy,
3424         // SwDoc::CopyWithFlyInFly). This rather obscure bugfix was introduced
3425         // for #63198# and #64896#, and apparently never really worked.
3426         pDoc->SetRedlineMove( pStt->nContent == 0 );
3427 
3428         if( pCSttNd )
3429         {
3430             SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
3431                                     ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
3432                                     : pDoc->GetTxtCollFromPool(
3433                                                 RES_POOLCOLL_STANDARD );
3434 
3435             pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
3436                                             SwNormalStartNode, pColl );
3437 
3438             SwNodeIndex aNdIdx( *pSttNd, 1 );
3439             SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode();
3440             SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
3441             pDoc->CopyRange( *this, aPos, false );
3442 
3443             // JP 08.10.98: die Vorlage vom EndNode ggfs. mit uebernehmen
3444             //              - ist im Doc::Copy nicht erwuenscht
3445             if( pCEndNd && pCEndNd != pCSttNd )
3446             {
3447                 SwCntntNode* pDestNd = aPos.nNode.GetNode().GetCntntNode();
3448                 if( pDestNd )
3449                 {
3450                     if( pDestNd->IsTxtNode() && pCEndNd->IsTxtNode() )
3451                         ((SwTxtNode*)pCEndNd)->CopyCollFmt(
3452                                             *(SwTxtNode*)pDestNd );
3453                     else
3454                         pDestNd->ChgFmtColl( pCEndNd->GetFmtColl() );
3455                 }
3456             }
3457         }
3458         else
3459         {
3460             pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
3461                                             SwNormalStartNode );
3462 
3463             if( pCEndNd )
3464             {
3465                 SwPosition aPos( *pSttNd->EndOfSectionNode() );
3466                 pDoc->CopyRange( *this, aPos, false );
3467             }
3468             else
3469             {
3470                 SwNodeIndex aInsPos( *pSttNd->EndOfSectionNode() );
3471                 SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 );
3472                 pDoc->CopyWithFlyInFly( aRg, 0, aInsPos );
3473             }
3474         }
3475         pCntntSect = new SwNodeIndex( *pSttNd );
3476 
3477         pDoc->SetCopyIsMove( bSaveCopyFlag );
3478         pDoc->SetRedlineMove( bSaveRdlMoveFlg );
3479     }
3480 }
3481 
DelCopyOfSection()3482 void SwRedline::DelCopyOfSection()
3483 {
3484     if( pCntntSect )
3485     {
3486         const SwPosition* pStt = Start(),
3487                         * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
3488 
3489         SwDoc* pDoc = GetDoc();
3490         SwPaM aPam( *pStt, *pEnd );
3491         SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
3492         SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
3493 
3494         if( !pCSttNd )
3495         {
3496             // damit die Indizies der anderen Redlines nicht mitverschoben
3497             // werden, diese aufs Ende setzen (ist exclusive).
3498             const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
3499             for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
3500             {
3501                 SwRedline* pRedl = rTbl[ n ];
3502                 if( pRedl->GetBound(sal_True) == *pStt )
3503                     pRedl->GetBound(sal_True) = *pEnd;
3504                 if( pRedl->GetBound(sal_False) == *pStt )
3505                     pRedl->GetBound(sal_False) = *pEnd;
3506             }
3507         }
3508 
3509         if( pCSttNd && pCEndNd )
3510         {
3511             // --> OD 2009-08-20 #i100466#
3512             // force a <join next> on <delete and join> operation
3513             pDoc->DeleteAndJoin( aPam, true );
3514             // <--
3515         }
3516         else if( pCSttNd || pCEndNd )
3517         {
3518             if( pCSttNd && !pCEndNd )
3519                 bDelLastPara = sal_True;
3520             pDoc->DeleteRange( aPam );
3521 
3522             if( bDelLastPara )
3523             {
3524                 // #100611# To prevent dangling references to the paragraph to
3525                 // be deleted, redline that point into this paragraph should be
3526                 // moved to the new end position. Since redlines in the redline
3527                 // table are sorted and the pEnd position is an endnode (see
3528                 // bDelLastPara condition above), only redlines before the
3529                 // current ones can be affected.
3530                 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
3531                 sal_uInt16 n = rTbl.GetPos( this );
3532                 ASSERT( n != USHRT_MAX, "How strange. We don't exist!" );
3533                 for( sal_Bool bBreak = sal_False; !bBreak && n > 0; )
3534                 {
3535                     --n;
3536                     bBreak = sal_True;
3537                     if( rTbl[ n ]->GetBound(sal_True) == *aPam.GetPoint() )
3538                     {
3539                         rTbl[ n ]->GetBound(sal_True) = *pEnd;
3540                         bBreak = sal_False;
3541                     }
3542                     if( rTbl[ n ]->GetBound(sal_False) == *aPam.GetPoint() )
3543                     {
3544                         rTbl[ n ]->GetBound(sal_False) = *pEnd;
3545                         bBreak = sal_False;
3546                     }
3547                 }
3548 
3549                 SwPosition aEnd( *pEnd );
3550                 *GetPoint() = *pEnd;
3551                 *GetMark() = *pEnd;
3552                 DeleteMark();
3553 
3554                 aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
3555                 aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
3556                 aPam.DeleteMark();
3557                 pDoc->DelFullPara( aPam );
3558             }
3559         }
3560         else
3561         {
3562             pDoc->DeleteRange( aPam );
3563         }
3564 
3565         if( pStt == GetPoint() )
3566             Exchange();
3567 
3568         DeleteMark();
3569     }
3570 }
3571 
MoveFromSection()3572 void SwRedline::MoveFromSection()
3573 {
3574     if( pCntntSect )
3575     {
3576         SwDoc* pDoc = GetDoc();
3577         const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
3578         SvPtrarr aBeforeArr( 16, 16 ), aBehindArr( 16, 16 );
3579         sal_uInt16 nMyPos = rTbl.GetPos( this );
3580         ASSERT( this, "this nicht im Array?" );
3581         sal_Bool bBreak = sal_False;
3582         sal_uInt16 n;
3583 
3584         for( n = nMyPos+1; !bBreak && n < rTbl.Count(); ++n )
3585         {
3586             bBreak = sal_True;
3587             if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() )
3588             {
3589                 void* pTmp = &rTbl[ n ]->GetBound(sal_True);
3590                 aBehindArr.Insert( pTmp, aBehindArr.Count());
3591                 bBreak = sal_False;
3592             }
3593             if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() )
3594             {
3595                 void* pTmp = &rTbl[ n ]->GetBound(sal_False);
3596                 aBehindArr.Insert( pTmp, aBehindArr.Count() );
3597                 bBreak = sal_False;
3598             }
3599         }
3600         for( bBreak = sal_False, n = nMyPos; !bBreak && n ; )
3601         {
3602             --n;
3603             bBreak = sal_True;
3604             if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() )
3605             {
3606                 void* pTmp = &rTbl[ n ]->GetBound(sal_True);
3607                 aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
3608                 bBreak = sal_False;
3609             }
3610             if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() )
3611             {
3612                 void* pTmp = &rTbl[ n ]->GetBound(sal_False);
3613                 aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
3614                 bBreak = sal_False;
3615             }
3616         }
3617 
3618         // --> OD 2009-03-17 #i95711#
3619         const SwNode* pKeptCntntSectNode( &pCntntSect->GetNode() );
3620         // <--
3621         {
3622             SwPaM aPam( pCntntSect->GetNode(),
3623                         *pCntntSect->GetNode().EndOfSectionNode(), 1,
3624                         ( bDelLastPara ? -2 : -1 ) );
3625             SwCntntNode* pCNd = aPam.GetCntntNode();
3626             if( pCNd )
3627                 aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
3628             else
3629                 aPam.GetPoint()->nNode++;
3630 
3631             SwFmtColl* pColl = pCNd && pCNd->Len() && aPam.GetPoint()->nNode !=
3632                                         aPam.GetMark()->nNode
3633                                 ? pCNd->GetFmtColl() : 0;
3634 
3635             SwNodeIndex aNdIdx( GetPoint()->nNode, -1 );
3636             sal_uInt16 nPos = GetPoint()->nContent.GetIndex();
3637 
3638             SwPosition aPos( *GetPoint() );
3639             if( bDelLastPara && *aPam.GetPoint() == *aPam.GetMark() )
3640             {
3641                 aPos.nNode--;
3642 
3643                 pDoc->AppendTxtNode( aPos );
3644             }
3645             else
3646             {
3647                 pDoc->MoveRange( aPam, aPos,
3648                     IDocumentContentOperations::DOC_MOVEALLFLYS );
3649             }
3650 
3651             SetMark();
3652             *GetPoint() = aPos;
3653             GetMark()->nNode = aNdIdx.GetIndex() + 1;
3654             pCNd = GetMark()->nNode.GetNode().GetCntntNode();
3655             GetMark()->nContent.Assign( pCNd, nPos );
3656 
3657             if( bDelLastPara )
3658             {
3659                 GetPoint()->nNode++;
3660                 GetPoint()->nContent.Assign( pCNd = GetCntntNode(), 0 );
3661                 bDelLastPara = sal_False;
3662             }
3663             else if( pColl )
3664                 pCNd = GetCntntNode();
3665 
3666             if( pColl && pCNd )
3667                 pCNd->ChgFmtColl( pColl );
3668         }
3669         // --> OD 2009-03-17 #i95771#
3670         // Under certain conditions the previous <SwDoc::Move(..)> has already
3671         // remove the change tracking section of this <SwRedline> instance from
3672         // the change tracking nodes area.
3673         // Thus, check, if <pCntntSect> still points to the change tracking section
3674         // by comparing it with the "indexed" <SwNode> instance copied before
3675         // perform the intrinsic move.
3676         // Note: Such condition is e.g. a "delete" change tracking only containing a table.
3677         if ( &pCntntSect->GetNode() == pKeptCntntSectNode )
3678         {
3679             pDoc->DeleteSection( &pCntntSect->GetNode() );
3680         }
3681         // <--
3682         delete pCntntSect, pCntntSect = 0;
3683 
3684         // #100611# adjustment of redline table positions must take start and
3685         // end into account, not point and mark.
3686         for( n = 0; n < aBeforeArr.Count(); ++n )
3687             *(SwPosition*)aBeforeArr[ n ] = *Start();
3688         for( n = 0; n < aBehindArr.Count(); ++n )
3689             *(SwPosition*)aBehindArr[ n ] = *End();
3690     }
3691     else
3692         InvalidateRange();
3693 }
3694 
3695 // fuers Undo
SetContentIdx(const SwNodeIndex * pIdx)3696 void SwRedline::SetContentIdx( const SwNodeIndex* pIdx )
3697 {
3698     if( pIdx && !pCntntSect )
3699     {
3700         pCntntSect = new SwNodeIndex( *pIdx );
3701         bIsVisible = sal_False;
3702     }
3703     else if( !pIdx && pCntntSect )
3704     {
3705         delete pCntntSect, pCntntSect = 0;
3706         bIsVisible = sal_False;
3707     }
3708 #ifdef DBG_UTIL
3709     else
3710         ASSERT( !this, "das ist keine gueltige Operation" );
3711 #endif
3712 }
3713 
CanCombine(const SwRedline & rRedl) const3714 sal_Bool SwRedline::CanCombine( const SwRedline& rRedl ) const
3715 {
3716     return  IsVisible() && rRedl.IsVisible() &&
3717             pRedlineData->CanCombine( *rRedl.pRedlineData );
3718 }
3719 
PushData(const SwRedline & rRedl,sal_Bool bOwnAsNext)3720 void SwRedline::PushData( const SwRedline& rRedl, sal_Bool bOwnAsNext )
3721 {
3722 //  SwRedlineData* pNew = new SwRedlineData( rRedl.GetType(),
3723 //                                           rRedl.GetAuthor() );
3724     SwRedlineData* pNew = new SwRedlineData( *rRedl.pRedlineData, sal_False );
3725     if( bOwnAsNext )
3726     {
3727         pNew->pNext = pRedlineData;
3728         pRedlineData = pNew;
3729     }
3730     else
3731     {
3732         pNew->pNext = pRedlineData->pNext;
3733         pRedlineData->pNext = pNew;
3734     }
3735 }
3736 
PopData()3737 sal_Bool SwRedline::PopData()
3738 {
3739     if( !pRedlineData->pNext )
3740         return sal_False;
3741     SwRedlineData* pCur = pRedlineData;
3742     pRedlineData = pCur->pNext;
3743     pCur->pNext = 0;
3744     delete pCur;
3745     return sal_True;
3746 }
3747 
GetStackCount() const3748 sal_uInt16 SwRedline::GetStackCount() const
3749 {
3750     sal_uInt16 nRet = 1;
3751     for( SwRedlineData* pCur = pRedlineData; pCur->pNext; ++nRet )
3752         pCur = pCur->pNext;
3753     return nRet;
3754 }
3755 
3756 // -> #111827#
GetAuthor(sal_uInt16 nPos) const3757 sal_uInt16 SwRedline::GetAuthor( sal_uInt16 nPos ) const
3758 {
3759     return GetRedlineData(nPos).nAuthor;
3760 }
3761 
GetAuthorString(sal_uInt16 nPos) const3762 const String& SwRedline::GetAuthorString( sal_uInt16 nPos ) const
3763 {
3764     return SW_MOD()->GetRedlineAuthor(GetRedlineData(nPos).nAuthor);
3765 }
3766 
GetTimeStamp(sal_uInt16 nPos) const3767 const DateTime& SwRedline::GetTimeStamp( sal_uInt16 nPos ) const
3768 {
3769     return GetRedlineData(nPos).aStamp;
3770 }
3771 
GetRealType(sal_uInt16 nPos) const3772 RedlineType_t SwRedline::GetRealType( sal_uInt16 nPos ) const
3773 {
3774     return GetRedlineData(nPos).eType;
3775 }
3776 
GetComment(sal_uInt16 nPos) const3777 const String& SwRedline::GetComment( sal_uInt16 nPos ) const
3778 {
3779     return GetRedlineData(nPos).sComment;
3780 }
3781 // <- #111827#
3782 
operator ==(const SwRedline & rCmp) const3783 int SwRedline::operator==( const SwRedline& rCmp ) const
3784 {
3785     return this == &rCmp;
3786 }
3787 
operator <(const SwRedline & rCmp) const3788 int SwRedline::operator<( const SwRedline& rCmp ) const
3789 {
3790     sal_Bool nResult = sal_False;
3791 
3792     if (*Start() < *rCmp.Start())
3793         nResult = sal_True;
3794     else if (*Start() == *rCmp.Start())
3795         if (*End() < *rCmp.End())
3796             nResult = sal_True;
3797 
3798     return nResult;
3799 }
3800 
3801 // -> #111827#
GetRedlineData(sal_uInt16 nPos) const3802 const SwRedlineData & SwRedline::GetRedlineData(sal_uInt16 nPos) const
3803 {
3804     SwRedlineData * pCur = pRedlineData;
3805 
3806     while (nPos > 0 && NULL != pCur->pNext)
3807     {
3808         pCur = pCur->pNext;
3809 
3810         nPos--;
3811     }
3812 
3813     ASSERT( 0 == nPos, "Pos angabe ist zu gross" );
3814 
3815     return *pCur;
3816 }
3817 
GetDescr(sal_uInt16 nPos)3818 String SwRedline::GetDescr(sal_uInt16 nPos)
3819 {
3820     String aResult;
3821 
3822     // get description of redline data (e.g.: "insert $1")
3823     aResult = GetRedlineData(nPos).GetDescr();
3824 
3825     SwPaM * pPaM = NULL;
3826     bool bDeletePaM = false;
3827 
3828     // if this redline is visible the content is in this PaM
3829     if (NULL == pCntntSect)
3830     {
3831         pPaM = this;
3832     }
3833     else // otherwise it is saved in pCntntSect
3834     {
3835         SwNodeIndex aTmpIdx( *pCntntSect->GetNode().EndOfSectionNode() );
3836         pPaM = new SwPaM(*pCntntSect, aTmpIdx );
3837         bDeletePaM = true;
3838     }
3839 
3840     // replace $1 in description by description of the redlines text
3841     String aTmpStr;
3842     aTmpStr += String(SW_RES(STR_START_QUOTE));
3843     aTmpStr += ShortenString(pPaM->GetTxt(), nUndoStringLength,
3844                              String(SW_RES(STR_LDOTS)));
3845     aTmpStr += String(SW_RES(STR_END_QUOTE));
3846 
3847     SwRewriter aRewriter;
3848     aRewriter.AddRule(UNDO_ARG1, aTmpStr);
3849 
3850     aResult = aRewriter.Apply(aResult);
3851 
3852     if (bDeletePaM)
3853         delete pPaM;
3854 
3855     return aResult;
3856 }
3857 // <- #111827#
3858 
3859 
IsInRedlines(const SwNode & rNode) const3860 bool SwDoc::IsInRedlines(const SwNode & rNode) const
3861 {
3862     SwPosition aPos(rNode);
3863     SwNode & rEndOfRedlines = GetNodes().GetEndOfRedlines();
3864     SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()),
3865                SwPosition(rEndOfRedlines));
3866 
3867     return aPam.ContainsPosition(aPos) ? true : false;
3868 }
3869