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