Line data Source code
1 :
2 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 : /*
4 : * This file is part of the LibreOffice project.
5 : *
6 : * This Source Code Form is subject to the terms of the Mozilla Public
7 : * License, v. 2.0. If a copy of the MPL was not distributed with this
8 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 : *
10 : * This file incorporates work covered by the following license notice:
11 : *
12 : * Licensed to the Apache Software Foundation (ASF) under one or more
13 : * contributor license agreements. See the NOTICE file distributed
14 : * with this work for additional information regarding copyright
15 : * ownership. The ASF licenses this file to you under the Apache
16 : * License, Version 2.0 (the "License"); you may not use this file
17 : * except in compliance with the License. You may obtain a copy of
18 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 : */
20 : #include <DocumentRedlineManager.hxx>
21 : #include <doc.hxx>
22 : #include <IDocumentUndoRedo.hxx>
23 : #include <IDocumentState.hxx>
24 : #include <redline.hxx>
25 : #include <UndoRedline.hxx>
26 : #include <docary.hxx>
27 : #include <ndtxt.hxx>
28 : #include <comcore.hrc>
29 : #include <swmodule.hxx>
30 : #include <editsh.hxx>
31 : #include <vcl/layout.hxx>
32 :
33 : using namespace com::sun::star;
34 :
35 : #ifdef DBG_UTIL
36 :
37 : #define _ERROR_PREFIX "redline table corrupted: "
38 :
39 : namespace
40 : {
41 : // helper function for lcl_CheckRedline
42 : // 1. make sure that pPos->nContent points into pPos->nNode
43 : // (or into the 'special' no-content-node-IndexReg)
44 : // 2. check that position is valid and doesn't point behind text
45 : static void lcl_CheckPosition( const SwPosition* pPos )
46 : {
47 : SwPosition aComparePos( *pPos );
48 : aComparePos.nContent.Assign(
49 : aComparePos.nNode.GetNode().GetCntntNode(), 0 );
50 : OSL_ENSURE( pPos->nContent.GetIdxReg() ==
51 : aComparePos.nContent.GetIdxReg(),
52 : _ERROR_PREFIX "illegal position" );
53 :
54 : SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
55 : if( pTxtNode == NULL )
56 : {
57 : OSL_ENSURE( pPos->nContent == 0,
58 : _ERROR_PREFIX "non-text-node with content" );
59 : }
60 : else
61 : {
62 : OSL_ENSURE( pPos->nContent >= 0 &&
63 : pPos->nContent <= pTxtNode->Len(),
64 : _ERROR_PREFIX "index behind text" );
65 : }
66 : }
67 :
68 : static void lcl_CheckPam( const SwPaM* pPam )
69 : {
70 : OSL_ENSURE( pPam != NULL, _ERROR_PREFIX "illegal argument" );
71 : lcl_CheckPosition( pPam->GetPoint() );
72 : lcl_CheckPosition( pPam->GetMark() );
73 : }
74 :
75 : // check validity of the redline table. Checks redline bounds, and make
76 : // sure the redlines are sorted and non-overlapping.
77 : static void lcl_CheckRedline( IDocumentRedlineAccess& redlineAccess )
78 : {
79 : const SwRedlineTbl& rTbl = redlineAccess.GetRedlineTbl();
80 :
81 : // verify valid redline positions
82 : for( sal_uInt16 i = 0; i < rTbl.size(); ++i )
83 : lcl_CheckPam( rTbl[ i ] );
84 :
85 : for( sal_uInt16 j = 0; j < rTbl.size(); ++j )
86 : {
87 : // check for empty redlines
88 : OSL_ENSURE( ( *(rTbl[j]->GetPoint()) != *(rTbl[j]->GetMark()) ) ||
89 : ( rTbl[j]->GetContentIdx() != NULL ),
90 : _ERROR_PREFIX "empty redline" );
91 : }
92 :
93 : // verify proper redline sorting
94 : for( sal_uInt16 n = 1; n < rTbl.size(); ++n )
95 : {
96 : const SwRangeRedline* pPrev = rTbl[ n-1 ];
97 : const SwRangeRedline* pCurrent = rTbl[ n ];
98 :
99 : // check redline sorting
100 : SAL_WARN_IF( *pPrev->Start() > *pCurrent->Start(), "sw",
101 : _ERROR_PREFIX "not sorted correctly" );
102 :
103 : // check for overlapping redlines
104 : SAL_WARN_IF( *pPrev->End() > *pCurrent->Start(), "sw",
105 : _ERROR_PREFIX "overlapping redlines" );
106 : }
107 : }
108 : }
109 :
110 : #define _CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc );
111 :
112 : #else
113 :
114 : #define _CHECK_REDLINE( pDoc )
115 :
116 : #endif
117 :
118 : namespace
119 : {
120 102 : static inline bool IsPrevPos( const SwPosition rPos1, const SwPosition rPos2 )
121 : {
122 : const SwCntntNode* pCNd;
123 102 : return 0 == rPos2.nContent.GetIndex() &&
124 0 : rPos2.nNode.GetIndex() - 1 == rPos1.nNode.GetIndex() &&
125 102 : 0 != ( pCNd = rPos1.nNode.GetNode().GetCntntNode() ) &&
126 102 : rPos1.nContent.GetIndex() == pCNd->Len();
127 : }
128 :
129 0 : static bool lcl_AcceptRedline( SwRedlineTbl& rArr, sal_uInt16& rPos,
130 : bool bCallDelete,
131 : const SwPosition* pSttRng = 0,
132 : const SwPosition* pEndRng = 0 )
133 : {
134 0 : bool bRet = true;
135 0 : SwRangeRedline* pRedl = rArr[ rPos ];
136 0 : SwPosition *pRStt = 0, *pREnd = 0;
137 0 : SwComparePosition eCmp = POS_OUTSIDE;
138 0 : if( pSttRng && pEndRng )
139 : {
140 0 : pRStt = pRedl->Start();
141 0 : pREnd = pRedl->End();
142 0 : eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
143 : }
144 :
145 0 : pRedl->InvalidateRange();
146 :
147 0 : switch( pRedl->GetType() )
148 : {
149 : case nsRedlineType_t::REDLINE_INSERT:
150 : case nsRedlineType_t::REDLINE_FORMAT:
151 : {
152 0 : bool bCheck = false, bReplace = false;
153 0 : switch( eCmp )
154 : {
155 : case POS_INSIDE:
156 0 : if( *pSttRng == *pRStt )
157 0 : pRedl->SetStart( *pEndRng, pRStt );
158 : else
159 : {
160 0 : if( *pEndRng != *pREnd )
161 : {
162 : // split up
163 0 : SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
164 0 : pNew->SetStart( *pEndRng );
165 0 : rArr.Insert( pNew ); ++rPos;
166 : }
167 0 : pRedl->SetEnd( *pSttRng, pREnd );
168 0 : bCheck = true;
169 : }
170 0 : break;
171 :
172 : case POS_OVERLAP_BEFORE:
173 0 : pRedl->SetStart( *pEndRng, pRStt );
174 0 : bReplace = true;
175 0 : break;
176 :
177 : case POS_OVERLAP_BEHIND:
178 0 : pRedl->SetEnd( *pSttRng, pREnd );
179 0 : bCheck = true;
180 0 : break;
181 :
182 : case POS_OUTSIDE:
183 : case POS_EQUAL:
184 0 : rArr.DeleteAndDestroy( rPos-- );
185 0 : break;
186 :
187 : default:
188 0 : bRet = false;
189 : }
190 :
191 0 : if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
192 : {
193 : // re-insert
194 0 : rArr.Remove( pRedl );
195 0 : rArr.Insert( pRedl );
196 : }
197 : }
198 0 : break;
199 : case nsRedlineType_t::REDLINE_DELETE:
200 : {
201 0 : SwDoc& rDoc = *pRedl->GetDoc();
202 0 : const SwPosition *pDelStt = 0, *pDelEnd = 0;
203 0 : bool bDelRedl = false;
204 0 : switch( eCmp )
205 : {
206 : case POS_INSIDE:
207 0 : if( bCallDelete )
208 : {
209 0 : pDelStt = pSttRng;
210 0 : pDelEnd = pEndRng;
211 : }
212 0 : break;
213 :
214 : case POS_OVERLAP_BEFORE:
215 0 : if( bCallDelete )
216 : {
217 0 : pDelStt = pRStt;
218 0 : pDelEnd = pEndRng;
219 : }
220 0 : break;
221 : case POS_OVERLAP_BEHIND:
222 0 : if( bCallDelete )
223 : {
224 0 : pDelStt = pREnd;
225 0 : pDelEnd = pSttRng;
226 : }
227 0 : break;
228 :
229 : case POS_OUTSIDE:
230 : case POS_EQUAL:
231 : {
232 0 : rArr.Remove( rPos-- );
233 0 : bDelRedl = true;
234 0 : if( bCallDelete )
235 : {
236 0 : pDelStt = pRedl->Start();
237 0 : pDelEnd = pRedl->End();
238 : }
239 : }
240 0 : break;
241 : default:
242 0 : bRet = false;
243 : }
244 :
245 0 : if( pDelStt && pDelEnd )
246 : {
247 0 : SwPaM aPam( *pDelStt, *pDelEnd );
248 0 : SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
249 0 : SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
250 :
251 0 : if( bDelRedl )
252 0 : delete pRedl;
253 :
254 0 : RedlineMode_t eOld = rDoc.getIDocumentRedlineAccess().GetRedlineMode();
255 0 : rDoc.getIDocumentRedlineAccess().SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
256 :
257 0 : if( pCSttNd && pCEndNd )
258 0 : rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam );
259 : else
260 : {
261 0 : rDoc.getIDocumentContentOperations().DeleteRange( aPam );
262 :
263 0 : if( pCSttNd && !pCEndNd )
264 : {
265 0 : aPam.GetBound( true ).nContent.Assign( 0, 0 );
266 0 : aPam.GetBound( false ).nContent.Assign( 0, 0 );
267 0 : aPam.DeleteMark();
268 0 : rDoc.getIDocumentContentOperations().DelFullPara( aPam );
269 : }
270 : }
271 0 : rDoc.getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
272 : }
273 0 : else if( bDelRedl )
274 0 : delete pRedl;
275 : }
276 0 : break;
277 :
278 : case nsRedlineType_t::REDLINE_FMTCOLL:
279 0 : rArr.DeleteAndDestroy( rPos-- );
280 0 : break;
281 :
282 : default:
283 0 : bRet = false;
284 : }
285 0 : return bRet;
286 : }
287 :
288 0 : static bool lcl_RejectRedline( SwRedlineTbl& rArr, sal_uInt16& rPos,
289 : bool bCallDelete,
290 : const SwPosition* pSttRng = 0,
291 : const SwPosition* pEndRng = 0 )
292 : {
293 0 : bool bRet = true;
294 0 : SwRangeRedline* pRedl = rArr[ rPos ];
295 0 : SwPosition *pRStt = 0, *pREnd = 0;
296 0 : SwComparePosition eCmp = POS_OUTSIDE;
297 0 : if( pSttRng && pEndRng )
298 : {
299 0 : pRStt = pRedl->Start();
300 0 : pREnd = pRedl->End();
301 0 : eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
302 : }
303 :
304 0 : pRedl->InvalidateRange();
305 :
306 0 : switch( pRedl->GetType() )
307 : {
308 : case nsRedlineType_t::REDLINE_INSERT:
309 : {
310 0 : SwDoc& rDoc = *pRedl->GetDoc();
311 0 : const SwPosition *pDelStt = 0, *pDelEnd = 0;
312 0 : bool bDelRedl = false;
313 0 : switch( eCmp )
314 : {
315 : case POS_INSIDE:
316 0 : if( bCallDelete )
317 : {
318 0 : pDelStt = pSttRng;
319 0 : pDelEnd = pEndRng;
320 : }
321 0 : break;
322 :
323 : case POS_OVERLAP_BEFORE:
324 0 : if( bCallDelete )
325 : {
326 0 : pDelStt = pRStt;
327 0 : pDelEnd = pEndRng;
328 : }
329 0 : break;
330 : case POS_OVERLAP_BEHIND:
331 0 : if( bCallDelete )
332 : {
333 0 : pDelStt = pREnd;
334 0 : pDelEnd = pSttRng;
335 : }
336 0 : break;
337 : case POS_OUTSIDE:
338 : case POS_EQUAL:
339 : {
340 : // delete the range again
341 0 : rArr.Remove( rPos-- );
342 0 : bDelRedl = true;
343 0 : if( bCallDelete )
344 : {
345 0 : pDelStt = pRedl->Start();
346 0 : pDelEnd = pRedl->End();
347 : }
348 : }
349 0 : break;
350 :
351 : default:
352 0 : bRet = false;
353 : }
354 0 : if( pDelStt && pDelEnd )
355 : {
356 0 : SwPaM aPam( *pDelStt, *pDelEnd );
357 :
358 0 : SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
359 0 : SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
360 :
361 0 : if( bDelRedl )
362 0 : delete pRedl;
363 :
364 0 : RedlineMode_t eOld = rDoc.getIDocumentRedlineAccess().GetRedlineMode();
365 0 : rDoc.getIDocumentRedlineAccess().SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
366 :
367 0 : if( pCSttNd && pCEndNd )
368 0 : rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam );
369 : else
370 : {
371 0 : rDoc.getIDocumentContentOperations().DeleteRange( aPam );
372 :
373 0 : if( pCSttNd && !pCEndNd )
374 : {
375 0 : aPam.GetBound( true ).nContent.Assign( 0, 0 );
376 0 : aPam.GetBound( false ).nContent.Assign( 0, 0 );
377 0 : aPam.DeleteMark();
378 0 : rDoc.getIDocumentContentOperations().DelFullPara( aPam );
379 : }
380 : }
381 0 : rDoc.getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
382 : }
383 0 : else if( bDelRedl )
384 0 : delete pRedl;
385 : }
386 0 : break;
387 : case nsRedlineType_t::REDLINE_DELETE:
388 : {
389 0 : SwRangeRedline* pNew = 0;
390 0 : bool bCheck = false, bReplace = false;
391 :
392 0 : switch( eCmp )
393 : {
394 : case POS_INSIDE:
395 : {
396 0 : if( 1 < pRedl->GetStackCount() )
397 : {
398 0 : pNew = new SwRangeRedline( *pRedl );
399 0 : pNew->PopData();
400 : }
401 0 : if( *pSttRng == *pRStt )
402 : {
403 0 : pRedl->SetStart( *pEndRng, pRStt );
404 0 : bReplace = true;
405 0 : if( pNew )
406 0 : pNew->SetEnd( *pEndRng );
407 : }
408 : else
409 : {
410 0 : if( *pEndRng != *pREnd )
411 : {
412 : // split up
413 0 : SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
414 0 : pCpy->SetStart( *pEndRng );
415 0 : rArr.Insert( pCpy ); ++rPos;
416 0 : if( pNew )
417 0 : pNew->SetEnd( *pEndRng );
418 : }
419 :
420 0 : pRedl->SetEnd( *pSttRng, pREnd );
421 0 : bCheck = true;
422 0 : if( pNew )
423 0 : pNew->SetStart( *pSttRng );
424 : }
425 : }
426 0 : break;
427 :
428 : case POS_OVERLAP_BEFORE:
429 0 : if( 1 < pRedl->GetStackCount() )
430 : {
431 0 : pNew = new SwRangeRedline( *pRedl );
432 0 : pNew->PopData();
433 : }
434 0 : pRedl->SetStart( *pEndRng, pRStt );
435 0 : bReplace = true;
436 0 : if( pNew )
437 0 : pNew->SetEnd( *pEndRng );
438 0 : break;
439 :
440 : case POS_OVERLAP_BEHIND:
441 0 : if( 1 < pRedl->GetStackCount() )
442 : {
443 0 : pNew = new SwRangeRedline( *pRedl );
444 0 : pNew->PopData();
445 : }
446 0 : pRedl->SetEnd( *pSttRng, pREnd );
447 0 : bCheck = true;
448 0 : if( pNew )
449 0 : pNew->SetStart( *pSttRng );
450 0 : break;
451 :
452 : case POS_OUTSIDE:
453 : case POS_EQUAL:
454 0 : if( !pRedl->PopData() )
455 : // deleting the RedlineObject is enough
456 0 : rArr.DeleteAndDestroy( rPos-- );
457 0 : break;
458 :
459 : default:
460 0 : bRet = false;
461 : }
462 :
463 0 : if( pNew )
464 : {
465 0 : rArr.Insert( pNew ); ++rPos;
466 : }
467 :
468 0 : if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
469 : {
470 : // re-insert
471 0 : rArr.Remove( pRedl );
472 0 : rArr.Insert( pRedl );
473 : }
474 : }
475 0 : break;
476 :
477 : case nsRedlineType_t::REDLINE_FORMAT:
478 : case nsRedlineType_t::REDLINE_FMTCOLL:
479 : {
480 0 : if( pRedl->GetExtraData() )
481 0 : pRedl->GetExtraData()->Reject( *pRedl );
482 0 : rArr.DeleteAndDestroy( rPos-- );
483 : }
484 0 : break;
485 :
486 : default:
487 0 : bRet = false;
488 : }
489 0 : return bRet;
490 : }
491 :
492 : typedef bool (*Fn_AcceptReject)( SwRedlineTbl& rArr, sal_uInt16& rPos,
493 : bool bCallDelete,
494 : const SwPosition* pSttRng,
495 : const SwPosition* pEndRng);
496 :
497 :
498 0 : static int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject,
499 : SwRedlineTbl& rArr, bool bCallDelete,
500 : const SwPaM& rPam)
501 : {
502 0 : sal_uInt16 n = 0;
503 0 : int nCount = 0;
504 :
505 0 : const SwPosition* pStt = rPam.Start(),
506 0 : * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
507 0 : : rPam.GetPoint();
508 0 : const SwRangeRedline* pFnd = rArr.FindAtPosition( *pStt, n, true );
509 0 : if( pFnd && // Is new a part of it?
510 0 : ( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd ))
511 : {
512 : // Only revoke the partial selection
513 0 : if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
514 0 : nCount++;
515 0 : ++n;
516 : }
517 :
518 0 : for( ; n < rArr.size(); ++n )
519 : {
520 0 : SwRangeRedline* pTmp = rArr[ n ];
521 0 : if( pTmp->HasMark() && pTmp->IsVisible() )
522 : {
523 0 : if( *pTmp->End() <= *pEnd )
524 : {
525 0 : if( (*fn_AcceptReject)( rArr, n, bCallDelete, 0, 0 ))
526 0 : nCount++;
527 : }
528 : else
529 : {
530 0 : if( *pTmp->Start() < *pEnd )
531 : {
532 : // Only revoke the partial selection
533 0 : if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
534 0 : nCount++;
535 : }
536 0 : break;
537 : }
538 : }
539 : }
540 0 : return nCount;
541 : }
542 :
543 0 : static void lcl_AdjustRedlineRange( SwPaM& rPam )
544 : {
545 : // The Selection is only in the ContentSection. If there are Redlines
546 : // to Non-ContentNodes before or after that, then the Selections
547 : // expand to them.
548 0 : SwPosition* pStt = rPam.Start(),
549 0 : * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
550 0 : : rPam.GetPoint();
551 0 : SwDoc* pDoc = rPam.GetDoc();
552 0 : if( !pStt->nContent.GetIndex() &&
553 0 : !pDoc->GetNodes()[ pStt->nNode.GetIndex() - 1 ]->IsCntntNode() )
554 : {
555 0 : const SwRangeRedline* pRedl = pDoc->getIDocumentRedlineAccess().GetRedline( *pStt, 0 );
556 0 : if( pRedl )
557 : {
558 0 : const SwPosition* pRStt = pRedl->Start();
559 0 : if( !pRStt->nContent.GetIndex() && pRStt->nNode.GetIndex() ==
560 0 : pStt->nNode.GetIndex() - 1 )
561 0 : *pStt = *pRStt;
562 : }
563 : }
564 0 : if( pEnd->nNode.GetNode().IsCntntNode() &&
565 0 : !pDoc->GetNodes()[ pEnd->nNode.GetIndex() + 1 ]->IsCntntNode() &&
566 0 : pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() )
567 : {
568 0 : const SwRangeRedline* pRedl = pDoc->getIDocumentRedlineAccess().GetRedline( *pEnd, 0 );
569 0 : if( pRedl )
570 : {
571 0 : const SwPosition* pREnd = pRedl->End();
572 0 : if( !pREnd->nContent.GetIndex() && pREnd->nNode.GetIndex() ==
573 0 : pEnd->nNode.GetIndex() + 1 )
574 0 : *pEnd = *pREnd;
575 : }
576 : }
577 0 : }
578 : }
579 :
580 : namespace sw
581 : {
582 :
583 5052 : DocumentRedlineManager::DocumentRedlineManager( SwDoc& i_rSwdoc ) : m_rSwdoc( i_rSwdoc ),
584 : meRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE)),
585 5052 : mpRedlineTbl( new SwRedlineTbl ),
586 5052 : mpExtraRedlineTbl ( new SwExtraRedlineTbl ),
587 : mpAutoFmtRedlnComment( 0 ),
588 : mbIsRedlineMove(false),
589 : mbReadlineChecked(false),
590 15156 : mnAutoFmtRedlnCommentNo( 0 )
591 : {
592 5052 : }
593 :
594 712746 : RedlineMode_t DocumentRedlineManager::GetRedlineMode() const
595 : {
596 712746 : return meRedlineMode;
597 : }
598 :
599 13628 : void DocumentRedlineManager::SetRedlineMode( RedlineMode_t eMode )
600 : {
601 13628 : if( meRedlineMode != eMode )
602 : {
603 780 : if( (nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode)
604 290 : || 0 == (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) )
605 : {
606 490 : bool bSaveInXMLImportFlag = m_rSwdoc.IsInXMLImport();
607 490 : m_rSwdoc.SetInXMLImport( false );
608 : // and then hide/display everything
609 490 : void (SwRangeRedline::*pFnc)( sal_uInt16 ) = 0;
610 :
611 490 : switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode )
612 : {
613 : case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE :
614 390 : pFnc = &SwRangeRedline::Show;
615 390 : break;
616 : case nsRedlineMode_t::REDLINE_SHOW_INSERT:
617 80 : pFnc = &SwRangeRedline::Hide;
618 80 : break;
619 : case nsRedlineMode_t::REDLINE_SHOW_DELETE:
620 2 : pFnc = &SwRangeRedline::ShowOriginal;
621 2 : break;
622 :
623 : default:
624 18 : pFnc = &SwRangeRedline::Hide;
625 18 : eMode = (RedlineMode_t)(eMode | nsRedlineMode_t::REDLINE_SHOW_INSERT);
626 18 : break;
627 : }
628 :
629 : _CHECK_REDLINE( *this )
630 :
631 490 : if( pFnc )
632 1470 : for( sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop )
633 1024 : for( sal_uInt16 i = 0; i < mpRedlineTbl->size(); ++i )
634 44 : ((*mpRedlineTbl)[ i ]->*pFnc)( nLoop );
635 : _CHECK_REDLINE( *this )
636 490 : m_rSwdoc.SetInXMLImport( bSaveInXMLImportFlag );
637 : }
638 780 : meRedlineMode = eMode;
639 780 : m_rSwdoc.getIDocumentState().SetModified();
640 : }
641 :
642 : // #TODO - add 'SwExtraRedlineTbl' also ?
643 13628 : }
644 :
645 539094 : bool DocumentRedlineManager::IsRedlineOn() const
646 : {
647 539094 : return IDocumentRedlineAccess::IsRedlineOn(meRedlineMode);
648 : }
649 :
650 300044 : bool DocumentRedlineManager::IsIgnoreRedline() const
651 : {
652 300044 : return (nsRedlineMode_t::REDLINE_IGNORE & meRedlineMode);
653 : }
654 :
655 12230 : void DocumentRedlineManager::SetRedlineMode_intern(RedlineMode_t eMode)
656 : {
657 12230 : meRedlineMode = eMode;
658 12230 : }
659 :
660 356214 : const SwRedlineTbl& DocumentRedlineManager::GetRedlineTbl() const
661 : {
662 356214 : return *mpRedlineTbl;
663 : }
664 :
665 757968 : SwRedlineTbl& DocumentRedlineManager::GetRedlineTbl()
666 : {
667 757968 : return *mpRedlineTbl;
668 : }
669 :
670 0 : const SwExtraRedlineTbl& DocumentRedlineManager::GetExtraRedlineTbl() const
671 : {
672 0 : return *mpExtraRedlineTbl;
673 : }
674 :
675 11211 : SwExtraRedlineTbl& DocumentRedlineManager::GetExtraRedlineTbl()
676 : {
677 11211 : return *mpExtraRedlineTbl;
678 : }
679 :
680 1844 : bool DocumentRedlineManager::HasExtraRedlineTbl() const
681 : {
682 1844 : return mpExtraRedlineTbl ? true : false;
683 : }
684 :
685 36838 : bool DocumentRedlineManager::IsInRedlines(const SwNode & rNode) const
686 : {
687 36838 : SwPosition aPos(rNode);
688 36838 : SwNode & rEndOfRedlines = m_rSwdoc.GetNodes().GetEndOfRedlines();
689 36838 : SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()),
690 110514 : SwPosition(rEndOfRedlines));
691 :
692 73676 : return aPam.ContainsPosition(aPos);
693 : }
694 :
695 17410 : bool DocumentRedlineManager::IsRedlineMove() const
696 : {
697 17410 : return mbIsRedlineMove;
698 : }
699 :
700 408 : void DocumentRedlineManager::SetRedlineMove(bool bFlag)
701 : {
702 408 : mbIsRedlineMove = bFlag;
703 408 : }
704 :
705 : /*
706 : Text means Text not "polluted" by Redlines.
707 :
708 : Behaviour of Insert-Redline:
709 : - in the Text - insert Redline Object
710 : - in InsertRedline (own) - ignore, existing is extended
711 : - in InsertRedline (others) - split up InsertRedline and
712 : insert Redline Object
713 : - in DeleteRedline - split up DeleteRedline or
714 : move at the end/beginning
715 :
716 : Behaviour of Delete-Redline:
717 : - in the Text - insert Redline Object
718 : - in DeleteRedline (own/others) - ignore
719 : - in InsertRedline (own) - ignore, but delete character
720 : - in InsertRedline (others) - split up InsertRedline and
721 : insert Redline Object
722 : - Text and own Insert overlap - delete Text in the own Insert,
723 : extend in the other Text
724 : (up to the Insert!)
725 : - Text and other Insert overlap - insert Redline Object, the
726 : other Insert is overlapped by
727 : the Delete
728 : */
729 5074 : bool DocumentRedlineManager::AppendRedline( SwRangeRedline* pNewRedl, bool bCallDelete )
730 : {
731 5074 : bool bMerged = false;
732 : _CHECK_REDLINE( *this )
733 :
734 5074 : if (IsRedlineOn() && !IsShowOriginal(meRedlineMode))
735 : {
736 4443 : pNewRedl->InvalidateRange();
737 :
738 4443 : if( m_rSwdoc.IsAutoFmtRedline() )
739 : {
740 0 : pNewRedl->SetAutoFmtFlag();
741 0 : if( mpAutoFmtRedlnComment && !mpAutoFmtRedlnComment->isEmpty() )
742 : {
743 0 : pNewRedl->SetComment( *mpAutoFmtRedlnComment );
744 0 : pNewRedl->SetSeqNo( mnAutoFmtRedlnCommentNo );
745 : }
746 : }
747 :
748 4443 : SwPosition* pStt = pNewRedl->Start(),
749 7546 : * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark()
750 7546 : : pNewRedl->GetPoint();
751 : {
752 4443 : SwTxtNode* pTxtNode = pStt->nNode.GetNode().GetTxtNode();
753 4443 : if( pTxtNode == NULL )
754 : {
755 0 : if( pStt->nContent > 0 )
756 : {
757 : OSL_ENSURE( false, "Redline start: non-text-node with content" );
758 0 : pStt->nContent = 0;
759 : }
760 : }
761 : else
762 : {
763 4443 : if( pStt->nContent > pTxtNode->Len() )
764 : {
765 : OSL_ENSURE( false, "Redline start: index behind text" );
766 0 : pStt->nContent = pTxtNode->Len();
767 : }
768 : }
769 4443 : pTxtNode = pEnd->nNode.GetNode().GetTxtNode();
770 4443 : if( pTxtNode == NULL )
771 : {
772 0 : if( pEnd->nContent > 0 )
773 : {
774 : OSL_ENSURE( false, "Redline end: non-text-node with content" );
775 0 : pEnd->nContent = 0;
776 : }
777 : }
778 : else
779 : {
780 4443 : if( pEnd->nContent > pTxtNode->Len() )
781 : {
782 : OSL_ENSURE( false, "Redline end: index behind text" );
783 0 : pEnd->nContent = pTxtNode->Len();
784 : }
785 : }
786 : }
787 4642 : if( ( *pStt == *pEnd ) &&
788 199 : ( pNewRedl->GetContentIdx() == NULL ) )
789 : { // Do not insert empty redlines
790 187 : delete pNewRedl;
791 187 : return false;
792 : }
793 4256 : bool bCompress = false;
794 4256 : sal_uInt16 n = 0;
795 : // look up the first Redline for the starting position
796 4256 : if( !GetRedline( *pStt, &n ) && n )
797 2830 : --n;
798 4256 : bool bDec = false;
799 :
800 167054 : for( ; pNewRedl && n < mpRedlineTbl->size(); bDec ? n : ++n )
801 : {
802 162798 : bDec = false;
803 :
804 162798 : SwRangeRedline* pRedl = (*mpRedlineTbl)[ n ];
805 162798 : SwPosition* pRStt = pRedl->Start(),
806 324424 : * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
807 324424 : : pRedl->GetPoint();
808 :
809 : // #i8518# remove empty redlines while we're at it
810 162808 : if( ( *pRStt == *pREnd ) &&
811 10 : ( pRedl->GetContentIdx() == NULL ) )
812 : {
813 2 : mpRedlineTbl->DeleteAndDestroy(n);
814 2 : continue;
815 : }
816 :
817 162796 : SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
818 :
819 162796 : switch( pNewRedl->GetType() )
820 : {
821 : case nsRedlineType_t::REDLINE_INSERT:
822 1342 : switch( pRedl->GetType() )
823 : {
824 : case nsRedlineType_t::REDLINE_INSERT:
825 1256 : if( pRedl->IsOwnRedline( *pNewRedl ) )
826 : {
827 659 : bool bDelete = false;
828 :
829 : // Merge if applicable?
830 2181 : if( (( POS_BEHIND == eCmpPos &&
831 1726 : IsPrevPos( *pREnd, *pStt ) ) ||
832 102 : ( POS_COLLIDE_START == eCmpPos ) ||
833 557 : ( POS_OVERLAP_BEHIND == eCmpPos ) ) &&
834 2280 : pRedl->CanCombine( *pNewRedl ) &&
835 547 : ( n+1 >= (sal_uInt16)mpRedlineTbl->size() ||
836 10 : ( *(*mpRedlineTbl)[ n+1 ]->Start() >= *pEnd &&
837 0 : *(*mpRedlineTbl)[ n+1 ]->Start() != *pREnd ) ) )
838 : {
839 527 : pRedl->SetEnd( *pEnd, pREnd );
840 527 : if( !pRedl->HasValidRange() )
841 : {
842 : // re-insert
843 0 : mpRedlineTbl->Remove( n );
844 0 : mpRedlineTbl->Insert( pRedl );
845 : }
846 :
847 527 : bMerged = true;
848 527 : bDelete = true;
849 : }
850 396 : else if( (( POS_BEFORE == eCmpPos &&
851 264 : IsPrevPos( *pEnd, *pRStt ) ) ||
852 132 : ( POS_COLLIDE_END == eCmpPos ) ||
853 0 : ( POS_OVERLAP_BEFORE == eCmpPos ) ) &&
854 132 : pRedl->CanCombine( *pNewRedl ) &&
855 0 : ( !n ||
856 0 : *(*mpRedlineTbl)[ n-1 ]->End() != *pRStt ))
857 : {
858 0 : pRedl->SetStart( *pStt, pRStt );
859 : // re-insert
860 0 : mpRedlineTbl->Remove( n );
861 0 : mpRedlineTbl->Insert( pRedl );
862 :
863 0 : bMerged = true;
864 0 : bDelete = true;
865 : }
866 132 : else if ( POS_OUTSIDE == eCmpPos )
867 : {
868 : // own insert-over-insert redlines:
869 : // just scrap the inside ones
870 0 : mpRedlineTbl->DeleteAndDestroy( n );
871 0 : bDec = true;
872 : }
873 132 : else if( POS_OVERLAP_BEHIND == eCmpPos )
874 : {
875 0 : *pStt = *pREnd;
876 0 : if( ( *pStt == *pEnd ) &&
877 0 : ( pNewRedl->GetContentIdx() == NULL ) )
878 0 : bDelete = true;
879 : }
880 132 : else if( POS_OVERLAP_BEFORE == eCmpPos )
881 : {
882 0 : *pEnd = *pRStt;
883 0 : if( ( *pStt == *pEnd ) &&
884 0 : ( pNewRedl->GetContentIdx() == NULL ) )
885 0 : bDelete = true;
886 : }
887 132 : else if( POS_INSIDE == eCmpPos || POS_EQUAL == eCmpPos)
888 0 : bDelete = true;
889 :
890 659 : if( bDelete )
891 : {
892 527 : delete pNewRedl, pNewRedl = 0;
893 527 : bCompress = true;
894 : }
895 : }
896 597 : else if( POS_INSIDE == eCmpPos )
897 : {
898 : // split up
899 0 : if( *pEnd != *pREnd )
900 : {
901 0 : SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
902 0 : pCpy->SetStart( *pEnd );
903 0 : mpRedlineTbl->Insert( pCpy );
904 : }
905 0 : pRedl->SetEnd( *pStt, pREnd );
906 0 : if( ( *pStt == *pRStt ) &&
907 0 : ( pRedl->GetContentIdx() == NULL ) )
908 : {
909 0 : mpRedlineTbl->DeleteAndDestroy( n );
910 0 : bDec = true;
911 : }
912 0 : else if( !pRedl->HasValidRange() )
913 : {
914 : // re-insert
915 0 : mpRedlineTbl->Remove( n );
916 0 : mpRedlineTbl->Insert( pRedl );
917 : }
918 : }
919 597 : else if ( POS_OUTSIDE == eCmpPos )
920 : {
921 : // handle overlapping redlines in broken documents
922 :
923 : // split up the new redline, since it covers the
924 : // existing redline. Insert the first part, and
925 : // progress with the remainder as usual
926 0 : SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl );
927 0 : pSplit->SetEnd( *pRStt );
928 0 : pNewRedl->SetStart( *pREnd );
929 0 : mpRedlineTbl->Insert( pSplit );
930 0 : if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
931 : {
932 0 : delete pNewRedl;
933 0 : pNewRedl = 0;
934 0 : bCompress = true;
935 : }
936 : }
937 597 : else if ( POS_OVERLAP_BEHIND == eCmpPos )
938 : {
939 : // handle overlapping redlines in broken documents
940 0 : pNewRedl->SetStart( *pREnd );
941 : }
942 597 : else if ( POS_OVERLAP_BEFORE == eCmpPos )
943 : {
944 : // handle overlapping redlines in broken documents
945 0 : *pEnd = *pRStt;
946 0 : if( ( *pStt == *pEnd ) &&
947 0 : ( pNewRedl->GetContentIdx() == NULL ) )
948 : {
949 0 : delete pNewRedl;
950 0 : pNewRedl = 0;
951 0 : bCompress = true;
952 : }
953 : }
954 1256 : break;
955 : case nsRedlineType_t::REDLINE_DELETE:
956 30 : if( POS_INSIDE == eCmpPos )
957 : {
958 : // split up
959 0 : if( *pEnd != *pREnd )
960 : {
961 0 : SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
962 0 : pCpy->SetStart( *pEnd );
963 0 : mpRedlineTbl->Insert( pCpy );
964 : }
965 0 : pRedl->SetEnd( *pStt, pREnd );
966 0 : if( ( *pStt == *pRStt ) &&
967 0 : ( pRedl->GetContentIdx() == NULL ) )
968 : {
969 0 : mpRedlineTbl->DeleteAndDestroy( n );
970 0 : bDec = true;
971 : }
972 0 : else if( !pRedl->HasValidRange() )
973 : {
974 : // re-insert
975 0 : mpRedlineTbl->Remove( n );
976 0 : mpRedlineTbl->Insert( pRedl, n );
977 : }
978 : }
979 30 : else if ( POS_OUTSIDE == eCmpPos )
980 : {
981 : // handle overlapping redlines in broken documents
982 :
983 : // split up the new redline, since it covers the
984 : // existing redline. Insert the first part, and
985 : // progress with the remainder as usual
986 0 : SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl );
987 0 : pSplit->SetEnd( *pRStt );
988 0 : pNewRedl->SetStart( *pREnd );
989 0 : mpRedlineTbl->Insert( pSplit );
990 0 : if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
991 : {
992 0 : delete pNewRedl;
993 0 : pNewRedl = 0;
994 0 : bCompress = true;
995 : }
996 : }
997 30 : else if ( POS_EQUAL == eCmpPos )
998 : {
999 : // handle identical redlines in broken documents
1000 : // delete old (delete) redline
1001 0 : mpRedlineTbl->DeleteAndDestroy( n );
1002 0 : bDec = true;
1003 : }
1004 30 : else if ( POS_OVERLAP_BEHIND == eCmpPos )
1005 : { // Another workaround for broken redlines
1006 0 : pNewRedl->SetStart( *pREnd );
1007 : }
1008 30 : break;
1009 : case nsRedlineType_t::REDLINE_FORMAT:
1010 54 : switch( eCmpPos )
1011 : {
1012 : case POS_OVERLAP_BEFORE:
1013 0 : pRedl->SetStart( *pEnd, pRStt );
1014 : // re-insert
1015 0 : mpRedlineTbl->Remove( n );
1016 0 : mpRedlineTbl->Insert( pRedl, n );
1017 0 : bDec = true;
1018 0 : break;
1019 :
1020 : case POS_OVERLAP_BEHIND:
1021 0 : pRedl->SetEnd( *pStt, pREnd );
1022 0 : if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
1023 : {
1024 0 : mpRedlineTbl->DeleteAndDestroy( n );
1025 0 : bDec = true;
1026 : }
1027 0 : break;
1028 :
1029 : case POS_EQUAL:
1030 : case POS_OUTSIDE:
1031 : // Overlaps the current one completely or has the
1032 : // same dimension, delete the old one
1033 44 : mpRedlineTbl->DeleteAndDestroy( n );
1034 44 : bDec = true;
1035 44 : break;
1036 :
1037 : case POS_INSIDE:
1038 : // Overlaps the current one completely,
1039 : // split or shorten the new one
1040 0 : if( *pEnd != *pREnd )
1041 : {
1042 0 : if( *pEnd != *pRStt )
1043 : {
1044 0 : SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
1045 0 : pNew->SetStart( *pEnd );
1046 0 : pRedl->SetEnd( *pStt, pREnd );
1047 0 : if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
1048 0 : mpRedlineTbl->DeleteAndDestroy( n );
1049 0 : AppendRedline( pNew, bCallDelete );
1050 0 : n = 0; // re-initialize
1051 0 : bDec = true;
1052 : }
1053 : }
1054 : else
1055 0 : pRedl->SetEnd( *pStt, pREnd );
1056 0 : break;
1057 : default:
1058 10 : break;
1059 : }
1060 54 : break;
1061 : default:
1062 2 : break;
1063 : }
1064 1342 : break;
1065 :
1066 : case nsRedlineType_t::REDLINE_DELETE:
1067 159584 : switch( pRedl->GetType() )
1068 : {
1069 : case nsRedlineType_t::REDLINE_DELETE:
1070 30244 : switch( eCmpPos )
1071 : {
1072 : case POS_OUTSIDE:
1073 : {
1074 : // Overlaps the current one completely,
1075 : // split the new one
1076 0 : if( *pEnd != *pREnd )
1077 : {
1078 0 : SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl );
1079 0 : pNew->SetStart( *pREnd );
1080 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1081 0 : AppendRedline( pNew, bCallDelete );
1082 0 : n = 0; // re-initialize
1083 0 : bDec = true;
1084 : }
1085 : else
1086 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1087 : }
1088 0 : break;
1089 :
1090 : case POS_INSIDE:
1091 : case POS_EQUAL:
1092 0 : delete pNewRedl, pNewRedl = 0;
1093 0 : bCompress = true;
1094 0 : break;
1095 :
1096 : case POS_OVERLAP_BEFORE:
1097 : case POS_OVERLAP_BEHIND:
1098 0 : if( pRedl->IsOwnRedline( *pNewRedl ) &&
1099 0 : pRedl->CanCombine( *pNewRedl ))
1100 : {
1101 : // If that's the case we can merge it, meaning
1102 : // the new one covers this well
1103 0 : if( POS_OVERLAP_BEHIND == eCmpPos )
1104 0 : pNewRedl->SetStart( *pRStt, pStt );
1105 : else
1106 0 : pNewRedl->SetEnd( *pREnd, pEnd );
1107 0 : mpRedlineTbl->DeleteAndDestroy( n );
1108 0 : bDec = true;
1109 : }
1110 0 : else if( POS_OVERLAP_BEHIND == eCmpPos )
1111 0 : pNewRedl->SetStart( *pREnd, pStt );
1112 : else
1113 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1114 0 : break;
1115 :
1116 : case POS_COLLIDE_START:
1117 : case POS_COLLIDE_END:
1118 1628 : if( pRedl->IsOwnRedline( *pNewRedl ) &&
1119 814 : pRedl->CanCombine( *pNewRedl ) )
1120 : {
1121 730 : if( IsHideChanges( meRedlineMode ))
1122 : {
1123 : // Before we can merge, we make it visible!
1124 : // We insert temporarily so that pNew is
1125 : // also dealt with when moving the indices.
1126 0 : mpRedlineTbl->Insert( pNewRedl );
1127 0 : pRedl->Show();
1128 0 : mpRedlineTbl->Remove( pNewRedl );
1129 0 : pRStt = pRedl->Start();
1130 0 : pREnd = pRedl->End();
1131 : }
1132 :
1133 : // If that's the case we can merge it, meaning
1134 : // the new one covers this well
1135 730 : if( POS_COLLIDE_START == eCmpPos )
1136 730 : pNewRedl->SetStart( *pRStt, pStt );
1137 : else
1138 0 : pNewRedl->SetEnd( *pREnd, pEnd );
1139 :
1140 : // delete current (below), and restart process with
1141 : // previous
1142 730 : sal_uInt16 nToBeDeleted = n;
1143 730 : bDec = true;
1144 :
1145 730 : if( *(pNewRedl->Start()) <= *pREnd )
1146 : {
1147 : // Whoooah, we just extended the new 'redline'
1148 : // beyond previous redlines, so better start
1149 : // again. Of course this is not supposed to
1150 : // happen, and in an ideal world it doesn't,
1151 : // but unfortunately this code is buggy and
1152 : // totally rotten so it does happen and we
1153 : // better fix it.
1154 730 : n = 0;
1155 730 : bDec = true;
1156 : }
1157 :
1158 730 : mpRedlineTbl->DeleteAndDestroy( nToBeDeleted );
1159 : }
1160 814 : break;
1161 : default:
1162 29430 : break;
1163 : }
1164 30244 : break;
1165 :
1166 : case nsRedlineType_t::REDLINE_INSERT:
1167 : {
1168 : // b62341295: Do not throw away redlines
1169 : // even if they are not allowed to be combined
1170 19528 : RedlineMode_t eOld = meRedlineMode;
1171 39054 : if( !( eOld & nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &&
1172 19526 : pRedl->IsOwnRedline( *pNewRedl ) )
1173 : {
1174 :
1175 : // Set to NONE, so that the Delete::Redo merges the Redline data correctly!
1176 : // The ShowMode needs to be retained!
1177 19520 : meRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
1178 19520 : switch( eCmpPos )
1179 : {
1180 : case POS_EQUAL:
1181 0 : bCompress = true;
1182 0 : mpRedlineTbl->DeleteAndDestroy( n );
1183 0 : bDec = true;
1184 : // no break!
1185 :
1186 : case POS_INSIDE:
1187 0 : if( bCallDelete )
1188 : {
1189 0 : meRedlineMode = (RedlineMode_t)(meRedlineMode | nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES);
1190 :
1191 : // DeleteAndJoin does not yield the
1192 : // desired result if there is no paragraph to
1193 : // join with, i.e. at the end of the document.
1194 : // For this case, we completely delete the
1195 : // paragraphs (if, of course, we also start on
1196 : // a paragraph boundary).
1197 0 : if( (pStt->nContent == 0) &&
1198 0 : pEnd->nNode.GetNode().IsEndNode() )
1199 : {
1200 0 : pEnd->nNode--;
1201 : pEnd->nContent.Assign(
1202 0 : pEnd->nNode.GetNode().GetTxtNode(), 0);
1203 0 : m_rSwdoc.getIDocumentContentOperations().DelFullPara( *pNewRedl );
1204 : }
1205 : else
1206 0 : m_rSwdoc.getIDocumentContentOperations().DeleteAndJoin( *pNewRedl );
1207 :
1208 0 : bCompress = true;
1209 : }
1210 0 : delete pNewRedl, pNewRedl = 0;
1211 0 : break;
1212 :
1213 : case POS_OUTSIDE:
1214 : {
1215 0 : mpRedlineTbl->Remove( n );
1216 0 : bDec = true;
1217 : // We insert temporarily so that pNew is
1218 : // also dealt with when moving the indices.
1219 0 : if( bCallDelete )
1220 : {
1221 0 : mpRedlineTbl->Insert( pNewRedl );
1222 0 : m_rSwdoc.getIDocumentContentOperations().DeleteAndJoin( *pRedl );
1223 0 : if( !mpRedlineTbl->Remove( pNewRedl ) )
1224 0 : pNewRedl = 0;
1225 : }
1226 0 : delete pRedl;
1227 : }
1228 0 : break;
1229 :
1230 : case POS_OVERLAP_BEFORE:
1231 : {
1232 0 : SwPaM aPam( *pRStt, *pEnd );
1233 :
1234 0 : if( *pEnd == *pREnd )
1235 0 : mpRedlineTbl->DeleteAndDestroy( n );
1236 : else
1237 : {
1238 0 : pRedl->SetStart( *pEnd, pRStt );
1239 : // re-insert
1240 0 : mpRedlineTbl->Remove( n );
1241 0 : mpRedlineTbl->Insert( pRedl, n );
1242 : }
1243 :
1244 0 : if( bCallDelete )
1245 : {
1246 : // We insert temporarily so that pNew is
1247 : // also dealt with when moving the indices.
1248 0 : mpRedlineTbl->Insert( pNewRedl );
1249 0 : m_rSwdoc.getIDocumentContentOperations().DeleteAndJoin( aPam );
1250 0 : if( !mpRedlineTbl->Remove( pNewRedl ) )
1251 0 : pNewRedl = 0;
1252 0 : n = 0; // re-initialize
1253 : }
1254 0 : bDec = true;
1255 : }
1256 0 : break;
1257 :
1258 : case POS_OVERLAP_BEHIND:
1259 : {
1260 0 : SwPaM aPam( *pStt, *pREnd );
1261 :
1262 0 : if( *pStt == *pRStt )
1263 : {
1264 0 : mpRedlineTbl->DeleteAndDestroy( n );
1265 0 : bDec = true;
1266 : }
1267 : else
1268 0 : pRedl->SetEnd( *pStt, pREnd );
1269 :
1270 0 : if( bCallDelete )
1271 : {
1272 : // We insert temporarily so that pNew is
1273 : // also dealt with when moving the indices.
1274 0 : mpRedlineTbl->Insert( pNewRedl );
1275 0 : m_rSwdoc.getIDocumentContentOperations().DeleteAndJoin( aPam );
1276 0 : if( !mpRedlineTbl->Remove( pNewRedl ) )
1277 0 : pNewRedl = 0;
1278 0 : n = 0; // re-initialize
1279 0 : bDec = true;
1280 0 : }
1281 : }
1282 0 : break;
1283 : default:
1284 19520 : break;
1285 : }
1286 :
1287 19520 : meRedlineMode = eOld;
1288 : }
1289 : else
1290 : {
1291 : // it may be necessary to split the existing redline in
1292 : // two. In this case, pRedl will be changed to cover
1293 : // only part of it's former range, and pNew will cover
1294 : // the remainder.
1295 8 : SwRangeRedline* pNew = 0;
1296 :
1297 8 : switch( eCmpPos )
1298 : {
1299 : case POS_EQUAL:
1300 : {
1301 4 : pRedl->PushData( *pNewRedl );
1302 4 : delete pNewRedl, pNewRedl = 0;
1303 4 : if( IsHideChanges( meRedlineMode ))
1304 0 : pRedl->Hide();
1305 4 : bCompress = true;
1306 : }
1307 4 : break;
1308 :
1309 : case POS_INSIDE:
1310 : {
1311 0 : if( *pRStt == *pStt )
1312 : {
1313 : // #i97421#
1314 : // redline w/out extent loops
1315 0 : if (*pStt != *pEnd)
1316 : {
1317 0 : pNewRedl->PushData( *pRedl, false );
1318 0 : pRedl->SetStart( *pEnd, pRStt );
1319 : // re-insert
1320 0 : mpRedlineTbl->Remove( n );
1321 0 : mpRedlineTbl->Insert( pRedl, n );
1322 0 : bDec = true;
1323 : }
1324 : }
1325 : else
1326 : {
1327 0 : pNewRedl->PushData( *pRedl, false );
1328 0 : if( *pREnd != *pEnd )
1329 : {
1330 0 : pNew = new SwRangeRedline( *pRedl );
1331 0 : pNew->SetStart( *pEnd );
1332 : }
1333 0 : pRedl->SetEnd( *pStt, pREnd );
1334 0 : if( !pRedl->HasValidRange() )
1335 : {
1336 : // re-insert
1337 0 : mpRedlineTbl->Remove( n );
1338 0 : mpRedlineTbl->Insert( pRedl, n );
1339 : }
1340 : }
1341 : }
1342 0 : break;
1343 :
1344 : case POS_OUTSIDE:
1345 : {
1346 0 : pRedl->PushData( *pNewRedl );
1347 0 : if( *pEnd == *pREnd )
1348 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1349 : else
1350 : {
1351 0 : pNew = new SwRangeRedline( *pNewRedl );
1352 0 : pNew->SetEnd( *pRStt );
1353 0 : pNewRedl->SetStart( *pREnd, pStt );
1354 : }
1355 0 : bCompress = true;
1356 : }
1357 0 : break;
1358 :
1359 : case POS_OVERLAP_BEFORE:
1360 : {
1361 0 : if( *pEnd == *pREnd )
1362 : {
1363 0 : pRedl->PushData( *pNewRedl );
1364 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1365 0 : if( IsHideChanges( meRedlineMode ))
1366 : {
1367 0 : mpRedlineTbl->Insert( pNewRedl );
1368 0 : pRedl->Hide();
1369 0 : mpRedlineTbl->Remove( pNewRedl );
1370 : }
1371 : }
1372 : else
1373 : {
1374 0 : pNew = new SwRangeRedline( *pRedl );
1375 0 : pNew->PushData( *pNewRedl );
1376 0 : pNew->SetEnd( *pEnd );
1377 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1378 0 : pRedl->SetStart( *pNew->End(), pRStt ) ;
1379 : // re-insert
1380 0 : mpRedlineTbl->Remove( n );
1381 0 : mpRedlineTbl->Insert( pRedl );
1382 0 : bDec = true;
1383 : }
1384 : }
1385 0 : break;
1386 :
1387 : case POS_OVERLAP_BEHIND:
1388 : {
1389 0 : if( *pStt == *pRStt )
1390 : {
1391 0 : pRedl->PushData( *pNewRedl );
1392 0 : pNewRedl->SetStart( *pREnd, pStt );
1393 0 : if( IsHideChanges( meRedlineMode ))
1394 : {
1395 0 : mpRedlineTbl->Insert( pNewRedl );
1396 0 : pRedl->Hide();
1397 0 : mpRedlineTbl->Remove( pNewRedl );
1398 : }
1399 : }
1400 : else
1401 : {
1402 0 : pNew = new SwRangeRedline( *pRedl );
1403 0 : pNew->PushData( *pNewRedl );
1404 0 : pNew->SetStart( *pStt );
1405 0 : pNewRedl->SetStart( *pREnd, pStt );
1406 0 : pRedl->SetEnd( *pNew->Start(), pREnd );
1407 0 : if( !pRedl->HasValidRange() )
1408 : {
1409 : // re-insert
1410 0 : mpRedlineTbl->Remove( n );
1411 0 : mpRedlineTbl->Insert( pRedl );
1412 : }
1413 : }
1414 : }
1415 0 : break;
1416 : default:
1417 4 : break;
1418 : }
1419 :
1420 : // insert the pNew part (if it exists)
1421 8 : if( pNew )
1422 : {
1423 0 : mpRedlineTbl->Insert( pNew );
1424 :
1425 : // pNew must be deleted if Insert() wasn't
1426 : // successful. But that can't happen, since pNew is
1427 : // part of the original pRedl redline.
1428 : // OSL_ENSURE( bRet, "Can't insert existing redline?" );
1429 :
1430 : // restart (now with pRedl being split up)
1431 0 : n = 0;
1432 0 : bDec = true;
1433 : }
1434 : }
1435 : }
1436 19528 : break;
1437 :
1438 : case nsRedlineType_t::REDLINE_FORMAT:
1439 48980 : switch( eCmpPos )
1440 : {
1441 : case POS_OVERLAP_BEFORE:
1442 0 : pRedl->SetStart( *pEnd, pRStt );
1443 : // re-insert
1444 0 : mpRedlineTbl->Remove( n );
1445 0 : mpRedlineTbl->Insert( pRedl, n );
1446 0 : bDec = true;
1447 0 : break;
1448 :
1449 : case POS_OVERLAP_BEHIND:
1450 0 : pRedl->SetEnd( *pStt, pREnd );
1451 0 : break;
1452 :
1453 : case POS_EQUAL:
1454 : case POS_OUTSIDE:
1455 : // Overlaps the current one completely or has the
1456 : // same dimension, delete the old one
1457 598 : mpRedlineTbl->DeleteAndDestroy( n );
1458 598 : bDec = true;
1459 598 : break;
1460 :
1461 : case POS_INSIDE:
1462 : // Overlaps the current one completely,
1463 : // split or shorten the new one
1464 0 : if( *pEnd != *pREnd )
1465 : {
1466 0 : if( *pEnd != *pRStt )
1467 : {
1468 0 : SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
1469 0 : pNew->SetStart( *pEnd );
1470 0 : pRedl->SetEnd( *pStt, pREnd );
1471 0 : if( ( *pStt == *pRStt ) &&
1472 0 : ( pRedl->GetContentIdx() == NULL ) )
1473 0 : mpRedlineTbl->DeleteAndDestroy( n );
1474 0 : AppendRedline( pNew, bCallDelete );
1475 0 : n = 0; // re-initialize
1476 0 : bDec = true;
1477 : }
1478 : }
1479 : else
1480 0 : pRedl->SetEnd( *pStt, pREnd );
1481 0 : break;
1482 : default:
1483 48382 : break;
1484 : }
1485 48980 : break;
1486 : default:
1487 60832 : break;
1488 : }
1489 159584 : break;
1490 :
1491 : case nsRedlineType_t::REDLINE_FORMAT:
1492 914 : switch( pRedl->GetType() )
1493 : {
1494 : case nsRedlineType_t::REDLINE_INSERT:
1495 : case nsRedlineType_t::REDLINE_DELETE:
1496 120 : switch( eCmpPos )
1497 : {
1498 : case POS_OVERLAP_BEFORE:
1499 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1500 0 : break;
1501 :
1502 : case POS_OVERLAP_BEHIND:
1503 0 : pNewRedl->SetStart( *pREnd, pStt );
1504 0 : break;
1505 :
1506 : case POS_EQUAL:
1507 : case POS_INSIDE:
1508 0 : delete pNewRedl, pNewRedl = 0;
1509 0 : break;
1510 :
1511 : case POS_OUTSIDE:
1512 : // Overlaps the current one completely,
1513 : // split or shorten the new one
1514 0 : if( *pEnd != *pREnd )
1515 : {
1516 0 : if( *pEnd != *pRStt )
1517 : {
1518 0 : SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl );
1519 0 : pNew->SetStart( *pREnd );
1520 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1521 0 : AppendRedline( pNew, bCallDelete );
1522 0 : n = 0; // re-initialize
1523 0 : bDec = true;
1524 : }
1525 : }
1526 : else
1527 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1528 0 : break;
1529 : default:
1530 120 : break;
1531 : }
1532 120 : break;
1533 : case nsRedlineType_t::REDLINE_FORMAT:
1534 262 : switch( eCmpPos )
1535 : {
1536 : case POS_OUTSIDE:
1537 : case POS_EQUAL:
1538 : {
1539 : // Overlaps the current one completely or has the
1540 : // same dimension, delete the old one
1541 0 : mpRedlineTbl->DeleteAndDestroy( n );
1542 0 : bDec = true;
1543 : }
1544 0 : break;
1545 :
1546 : case POS_INSIDE:
1547 0 : if( pRedl->IsOwnRedline( *pNewRedl ) &&
1548 0 : pRedl->CanCombine( *pNewRedl ))
1549 : // own one can be ignored completely
1550 0 : delete pNewRedl, pNewRedl = 0;
1551 :
1552 0 : else if( *pREnd == *pEnd )
1553 : // or else only shorten the current one
1554 0 : pRedl->SetEnd( *pStt, pREnd );
1555 0 : else if( *pRStt == *pStt )
1556 : {
1557 : // or else only shorten the current one
1558 0 : pRedl->SetStart( *pEnd, pRStt );
1559 : // re-insert
1560 0 : mpRedlineTbl->Remove( n );
1561 0 : mpRedlineTbl->Insert( pRedl, n );
1562 0 : bDec = true;
1563 : }
1564 : else
1565 : {
1566 : // If it lies completely within the current one
1567 : // we need to split it
1568 0 : SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
1569 0 : pNew->SetStart( *pEnd );
1570 0 : pRedl->SetEnd( *pStt, pREnd );
1571 0 : AppendRedline( pNew, bCallDelete );
1572 0 : n = 0; // re-initialize
1573 0 : bDec = true;
1574 : }
1575 0 : break;
1576 :
1577 : case POS_OVERLAP_BEFORE:
1578 : case POS_OVERLAP_BEHIND:
1579 0 : if( pRedl->IsOwnRedline( *pNewRedl ) &&
1580 0 : pRedl->CanCombine( *pNewRedl ))
1581 : {
1582 : // If that's the case we can merge it, meaning
1583 : // the new one covers this well
1584 0 : if( POS_OVERLAP_BEHIND == eCmpPos )
1585 0 : pNewRedl->SetStart( *pRStt, pStt );
1586 : else
1587 0 : pNewRedl->SetEnd( *pREnd, pEnd );
1588 0 : mpRedlineTbl->DeleteAndDestroy( n );
1589 0 : bDec = false;
1590 : }
1591 0 : else if( POS_OVERLAP_BEHIND == eCmpPos )
1592 0 : pNewRedl->SetStart( *pREnd, pStt );
1593 : else
1594 0 : pNewRedl->SetEnd( *pRStt, pEnd );
1595 0 : break;
1596 :
1597 : case POS_COLLIDE_END:
1598 0 : if( pRedl->IsOwnRedline( *pNewRedl ) &&
1599 0 : pRedl->CanCombine( *pNewRedl ) && n &&
1600 0 : *(*mpRedlineTbl)[ n-1 ]->End() < *pStt )
1601 : {
1602 : // If that's the case we can merge it, meaning
1603 : // the new one covers this well
1604 0 : pNewRedl->SetEnd( *pREnd, pEnd );
1605 0 : mpRedlineTbl->DeleteAndDestroy( n );
1606 0 : bDec = true;
1607 : }
1608 0 : break;
1609 : case POS_COLLIDE_START:
1610 630 : if( pRedl->IsOwnRedline( *pNewRedl ) &&
1611 356 : pRedl->CanCombine( *pNewRedl ) &&
1612 356 : n+1 < (sal_uInt16)mpRedlineTbl->size() &&
1613 0 : *(*mpRedlineTbl)[ n+1 ]->Start() < *pEnd )
1614 : {
1615 : // If that's the case we can merge it, meaning
1616 : // the new one covers this well
1617 0 : pNewRedl->SetStart( *pRStt, pStt );
1618 0 : mpRedlineTbl->DeleteAndDestroy( n );
1619 0 : bDec = true;
1620 : }
1621 210 : break;
1622 : default:
1623 52 : break;
1624 : }
1625 262 : break;
1626 : default:
1627 532 : break;
1628 : }
1629 914 : break;
1630 :
1631 : case nsRedlineType_t::REDLINE_FMTCOLL:
1632 : // How should we behave here?
1633 : // insert as is
1634 0 : break;
1635 : default:
1636 956 : break;
1637 : }
1638 : }
1639 :
1640 4256 : if( pNewRedl )
1641 : {
1642 3737 : if( ( *pStt == *pEnd ) &&
1643 12 : ( pNewRedl->GetContentIdx() == NULL ) )
1644 : { // Do not insert empty redlines
1645 0 : delete pNewRedl;
1646 0 : pNewRedl = 0;
1647 : }
1648 : else
1649 3725 : mpRedlineTbl->Insert( pNewRedl );
1650 : }
1651 :
1652 4256 : if( bCompress )
1653 531 : CompressRedlines();
1654 : }
1655 : else
1656 : {
1657 631 : if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
1658 : {
1659 0 : RedlineMode_t eOld = meRedlineMode;
1660 : // Set to NONE, so that the Delete::Redo merges the Redline data correctly!
1661 : // The ShowMode needs to be retained!
1662 0 : meRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
1663 0 : m_rSwdoc.getIDocumentContentOperations().DeleteAndJoin( *pNewRedl );
1664 0 : meRedlineMode = eOld;
1665 : }
1666 631 : delete pNewRedl, pNewRedl = 0;
1667 : }
1668 : _CHECK_REDLINE( *this )
1669 :
1670 4887 : return ( 0 != pNewRedl ) || bMerged;
1671 : }
1672 :
1673 56 : bool DocumentRedlineManager::AppendTableRowRedline( SwTableRowRedline* pNewRedl, bool bCallDelete )
1674 : {
1675 : (void)bCallDelete;
1676 :
1677 : // #TODO - equivelant for 'SwTableRowRedline'
1678 56 : bool bMerged = false;
1679 : /*
1680 : _CHECK_REDLINE( this )
1681 : */
1682 :
1683 56 : if (IsRedlineOn() && !IsShowOriginal(meRedlineMode))
1684 : {
1685 : // #TODO - equivelant for 'SwTableRowRedline'
1686 : /*
1687 : pNewRedl->InvalidateRange();
1688 : */
1689 :
1690 : // Make equivelant of 'AppendRedline' checks inside here too
1691 :
1692 56 : mpExtraRedlineTbl->Insert( pNewRedl );
1693 : }
1694 : else
1695 : {
1696 : // TO DO - equivelant for 'SwTableRowRedline'
1697 : /*
1698 : if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
1699 : {
1700 : RedlineMode_t eOld = meRedlineMode;
1701 : // Set to NONE, so that the Delete::Redo merges the Redline data correctly!
1702 : // The ShowMode needs to be retained!
1703 : meRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
1704 : DeleteAndJoin( *pNewRedl );
1705 : meRedlineMode = eOld;
1706 : }
1707 : delete pNewRedl, pNewRedl = 0;
1708 : */
1709 : }
1710 : // #TODO - equivelant for 'SwTableRowRedline'
1711 : /*
1712 : _CHECK_REDLINE( this )
1713 : */
1714 :
1715 56 : return ( 0 != pNewRedl ) || bMerged;
1716 : }
1717 :
1718 12 : bool DocumentRedlineManager::AppendTableCellRedline( SwTableCellRedline* pNewRedl, bool bCallDelete )
1719 : {
1720 : (void)bCallDelete;
1721 :
1722 : // #TODO - equivelant for 'SwTableCellRedline'
1723 12 : bool bMerged = false;
1724 : /*
1725 : _CHECK_REDLINE( this )
1726 : */
1727 :
1728 12 : if (IsRedlineOn() && !IsShowOriginal(meRedlineMode))
1729 : {
1730 : // #TODO - equivelant for 'SwTableCellRedline'
1731 : /*
1732 : pNewRedl->InvalidateRange();
1733 : */
1734 :
1735 : // Make equivelant of 'AppendRedline' checks inside here too
1736 :
1737 12 : mpExtraRedlineTbl->Insert( pNewRedl );
1738 : }
1739 : else
1740 : {
1741 : // TO DO - equivelant for 'SwTableCellRedline'
1742 : /*
1743 : if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
1744 : {
1745 : RedlineMode_t eOld = meRedlineMode;
1746 : // Set to NONE, so that the Delete::Redo merges the Redline data correctly!
1747 : // The ShowMode needs to be retained!
1748 : meRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
1749 : DeleteAndJoin( *pNewRedl );
1750 : meRedlineMode = eOld;
1751 : }
1752 : delete pNewRedl, pNewRedl = 0;
1753 : */
1754 : }
1755 : // #TODO - equivelant for 'SwTableCellRedline'
1756 : /*
1757 : _CHECK_REDLINE( this )
1758 : */
1759 :
1760 12 : return ( 0 != pNewRedl ) || bMerged;
1761 : }
1762 :
1763 659 : void DocumentRedlineManager::CompressRedlines()
1764 : {
1765 : _CHECK_REDLINE( *this )
1766 :
1767 659 : void (SwRangeRedline::*pFnc)(sal_uInt16) = 0;
1768 659 : switch( nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode )
1769 : {
1770 : case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
1771 293 : pFnc = &SwRangeRedline::Show;
1772 293 : break;
1773 : case nsRedlineMode_t::REDLINE_SHOW_INSERT:
1774 354 : pFnc = &SwRangeRedline::Hide;
1775 354 : break;
1776 : }
1777 :
1778 : // Try to merge identical ones
1779 7236 : for( sal_uInt16 n = 1; n < mpRedlineTbl->size(); ++n )
1780 : {
1781 6577 : SwRangeRedline* pPrev = (*mpRedlineTbl)[ n-1 ],
1782 6577 : * pCur = (*mpRedlineTbl)[ n ];
1783 6577 : const SwPosition* pPrevStt = pPrev->Start(),
1784 6577 : * pPrevEnd = pPrevStt == pPrev->GetPoint()
1785 6577 : ? pPrev->GetMark() : pPrev->GetPoint();
1786 6577 : const SwPosition* pCurStt = pCur->Start(),
1787 6577 : * pCurEnd = pCurStt == pCur->GetPoint()
1788 6577 : ? pCur->GetMark() : pCur->GetPoint();
1789 18211 : if( *pPrevEnd == *pCurStt && pPrev->CanCombine( *pCur ) &&
1790 976 : pPrevStt->nNode.GetNode().StartOfSectionNode() ==
1791 8529 : pCurEnd->nNode.GetNode().StartOfSectionNode() &&
1792 976 : !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() )
1793 : {
1794 : // we then can merge them
1795 976 : pPrev->Show();
1796 976 : pCur->Show();
1797 :
1798 976 : pPrev->SetEnd( *pCur->End() );
1799 976 : mpRedlineTbl->DeleteAndDestroy( n );
1800 976 : --n;
1801 976 : if( pFnc )
1802 950 : (pPrev->*pFnc)(0);
1803 : }
1804 : }
1805 : _CHECK_REDLINE( *this )
1806 :
1807 : // #TODO - add 'SwExtraRedlineTbl' also ?
1808 659 : }
1809 :
1810 2404 : bool DocumentRedlineManager::SplitRedline( const SwPaM& rRange )
1811 : {
1812 2404 : bool bChg = false;
1813 2404 : sal_uInt16 n = 0;
1814 2404 : const SwPosition* pStt = rRange.Start(),
1815 2404 : * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
1816 2404 : : rRange.GetPoint();
1817 2404 : GetRedline( *pStt, &n );
1818 2690 : for( ; n < mpRedlineTbl->size() ; ++n )
1819 : {
1820 456 : SwRangeRedline* pTmp = (*mpRedlineTbl)[ n ];
1821 456 : SwPosition* pTStt = pTmp->Start(),
1822 908 : * pTEnd = pTStt == pTmp->GetPoint() ? pTmp->GetMark()
1823 908 : : pTmp->GetPoint();
1824 940 : if( *pTStt <= *pStt && *pStt <= *pTEnd &&
1825 484 : *pTStt <= *pEnd && *pEnd <= *pTEnd )
1826 : {
1827 0 : bChg = true;
1828 0 : int nn = 0;
1829 0 : if( *pStt == *pTStt )
1830 0 : nn += 1;
1831 0 : if( *pEnd == *pTEnd )
1832 0 : nn += 2;
1833 :
1834 0 : SwRangeRedline* pNew = 0;
1835 0 : switch( nn )
1836 : {
1837 : case 0:
1838 0 : pNew = new SwRangeRedline( *pTmp );
1839 0 : pTmp->SetEnd( *pStt, pTEnd );
1840 0 : pNew->SetStart( *pEnd );
1841 0 : break;
1842 :
1843 : case 1:
1844 0 : *pTStt = *pEnd;
1845 0 : break;
1846 :
1847 : case 2:
1848 0 : *pTEnd = *pStt;
1849 0 : break;
1850 :
1851 : case 3:
1852 0 : pTmp->InvalidateRange();
1853 0 : mpRedlineTbl->DeleteAndDestroy( n-- );
1854 0 : pTmp = 0;
1855 0 : break;
1856 : }
1857 0 : if( pTmp && !pTmp->HasValidRange() )
1858 : {
1859 : // re-insert
1860 0 : mpRedlineTbl->Remove( n );
1861 0 : mpRedlineTbl->Insert( pTmp, n );
1862 : }
1863 0 : if( pNew )
1864 0 : mpRedlineTbl->Insert( pNew, n );
1865 : }
1866 456 : else if( *pEnd < *pTStt )
1867 170 : break;
1868 : }
1869 2404 : return bChg;
1870 :
1871 : // #TODO - add 'SwExtraRedlineTbl' also ?
1872 : }
1873 :
1874 7718 : bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
1875 : sal_uInt16 nDelType )
1876 : {
1877 23142 : if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & meRedlineMode ||
1878 15424 : !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
1879 12 : return false;
1880 :
1881 7706 : bool bChg = false;
1882 :
1883 7706 : if (bSaveInUndo && m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
1884 : {
1885 14 : SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange );
1886 14 : if( pUndo->GetRedlSaveCount() )
1887 : {
1888 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
1889 : }
1890 : else
1891 14 : delete pUndo;
1892 : }
1893 :
1894 7706 : const SwPosition* pStt = rRange.Start(),
1895 7706 : * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
1896 7706 : : rRange.GetPoint();
1897 7706 : sal_uInt16 n = 0;
1898 7706 : GetRedline( *pStt, &n );
1899 8614 : for( ; n < mpRedlineTbl->size() ; ++n )
1900 : {
1901 908 : SwRangeRedline* pRedl = (*mpRedlineTbl)[ n ];
1902 908 : if( USHRT_MAX != nDelType && nDelType != pRedl->GetType() )
1903 0 : continue;
1904 :
1905 908 : SwPosition* pRStt = pRedl->Start(),
1906 1062 : * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
1907 1062 : : pRedl->GetPoint();
1908 908 : switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
1909 : {
1910 : case POS_EQUAL:
1911 : case POS_OUTSIDE:
1912 760 : pRedl->InvalidateRange();
1913 760 : mpRedlineTbl->DeleteAndDestroy( n-- );
1914 760 : bChg = true;
1915 760 : break;
1916 :
1917 : case POS_OVERLAP_BEFORE:
1918 0 : pRedl->InvalidateRange();
1919 0 : pRedl->SetStart( *pEnd, pRStt );
1920 : // re-insert
1921 0 : mpRedlineTbl->Remove( n );
1922 0 : mpRedlineTbl->Insert( pRedl );
1923 0 : --n;
1924 0 : break;
1925 :
1926 : case POS_OVERLAP_BEHIND:
1927 0 : pRedl->InvalidateRange();
1928 0 : pRedl->SetEnd( *pStt, pREnd );
1929 0 : if( !pRedl->HasValidRange() )
1930 : {
1931 : // re-insert
1932 0 : mpRedlineTbl->Remove( n );
1933 0 : mpRedlineTbl->Insert( pRedl );
1934 0 : --n;
1935 : }
1936 0 : break;
1937 :
1938 : case POS_INSIDE:
1939 : {
1940 : // this one needs to be splitted
1941 0 : pRedl->InvalidateRange();
1942 0 : if( *pRStt == *pStt )
1943 : {
1944 0 : pRedl->SetStart( *pEnd, pRStt );
1945 : // re-insert
1946 0 : mpRedlineTbl->Remove( n );
1947 0 : mpRedlineTbl->Insert( pRedl );
1948 0 : --n;
1949 : }
1950 : else
1951 : {
1952 : SwRangeRedline* pCpy;
1953 0 : if( *pREnd != *pEnd )
1954 : {
1955 0 : pCpy = new SwRangeRedline( *pRedl );
1956 0 : pCpy->SetStart( *pEnd );
1957 : }
1958 : else
1959 0 : pCpy = 0;
1960 0 : pRedl->SetEnd( *pStt, pREnd );
1961 0 : if( !pRedl->HasValidRange() )
1962 : {
1963 : // re-insert
1964 0 : mpRedlineTbl->Remove( pRedl );
1965 0 : mpRedlineTbl->Insert( pRedl );
1966 0 : --n;
1967 : }
1968 0 : if( pCpy )
1969 0 : mpRedlineTbl->Insert( pCpy );
1970 : }
1971 : }
1972 0 : break;
1973 :
1974 : case POS_COLLIDE_END:
1975 : case POS_BEFORE:
1976 148 : n = mpRedlineTbl->size();
1977 148 : break;
1978 : default:
1979 0 : break;
1980 : }
1981 : }
1982 :
1983 7706 : if( bChg )
1984 96 : m_rSwdoc.getIDocumentState().SetModified();
1985 :
1986 7706 : return bChg;
1987 :
1988 : // #TODO - add 'SwExtraRedlineTbl' also ?
1989 : }
1990 :
1991 6994 : bool DocumentRedlineManager::DeleteRedline( const SwStartNode& rNode, bool bSaveInUndo,
1992 : sal_uInt16 nDelType )
1993 : {
1994 6994 : SwPaM aTemp(*rNode.EndOfSectionNode(), rNode);
1995 6994 : return DeleteRedline(aTemp, bSaveInUndo, nDelType);
1996 : }
1997 :
1998 604168 : sal_uInt16 DocumentRedlineManager::GetRedlinePos( const SwNode& rNd, sal_uInt16 nType ) const
1999 : {
2000 604168 : const sal_uLong nNdIdx = rNd.GetIndex();
2001 774170 : for( sal_uInt16 n = 0; n < mpRedlineTbl->size() ; ++n )
2002 : {
2003 181778 : const SwRangeRedline* pTmp = (*mpRedlineTbl)[ n ];
2004 181778 : sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
2005 181778 : nMk = pTmp->GetMark()->nNode.GetIndex();
2006 181778 : if( nPt < nMk ) { long nTmp = nMk; nMk = nPt; nPt = nTmp; }
2007 :
2008 181778 : if( ( USHRT_MAX == nType || nType == pTmp->GetType()) &&
2009 357671 : nMk <= nNdIdx && nNdIdx <= nPt )
2010 5891 : return n;
2011 :
2012 175887 : if( nMk > nNdIdx )
2013 5885 : break;
2014 : }
2015 598277 : return USHRT_MAX;
2016 :
2017 : // #TODO - add 'SwExtraRedlineTbl' also ?
2018 : }
2019 :
2020 16168 : const SwRangeRedline* DocumentRedlineManager::GetRedline( const SwPosition& rPos,
2021 : sal_uInt16* pFndPos ) const
2022 : {
2023 16168 : sal_uInt16 nO = mpRedlineTbl->size(), nM, nU = 0;
2024 16168 : if( nO > 0 )
2025 : {
2026 7710 : nO--;
2027 54408 : while( nU <= nO )
2028 : {
2029 40842 : nM = nU + ( nO - nU ) / 2;
2030 40842 : const SwRangeRedline* pRedl = (*mpRedlineTbl)[ nM ];
2031 40842 : const SwPosition* pStt = pRedl->Start();
2032 40842 : const SwPosition* pEnd = pStt == pRedl->GetPoint()
2033 35224 : ? pRedl->GetMark()
2034 76066 : : pRedl->GetPoint();
2035 81612 : if( pEnd == pStt
2036 : ? *pStt == rPos
2037 40770 : : ( *pStt <= rPos && rPos < *pEnd ) )
2038 : {
2039 3592 : while( nM && rPos == *(*mpRedlineTbl)[ nM - 1 ]->End() &&
2040 1038 : rPos == *(*mpRedlineTbl)[ nM - 1 ]->Start() )
2041 : {
2042 0 : --nM;
2043 0 : pRedl = (*mpRedlineTbl)[ nM ];
2044 : }
2045 : // if there are format and insert changes in the same position
2046 : // show insert change first.
2047 : // since the redlines are sorted by position, only check the redline
2048 : // before and after the current redline
2049 1277 : if( nsRedlineType_t::REDLINE_FORMAT == pRedl->GetType() )
2050 : {
2051 1922 : if( nM && rPos >= *(*mpRedlineTbl)[ nM - 1 ]->Start() &&
2052 1854 : rPos <= *(*mpRedlineTbl)[ nM - 1 ]->End() &&
2053 572 : ( nsRedlineType_t::REDLINE_INSERT == (*mpRedlineTbl)[ nM - 1 ]->GetType() ) )
2054 : {
2055 46 : --nM;
2056 46 : pRedl = (*mpRedlineTbl)[ nM ];
2057 : }
2058 2248 : else if( ( nM + 1 ) <= nO && rPos >= *(*mpRedlineTbl)[ nM + 1 ]->Start() &&
2059 1652 : rPos <= *(*mpRedlineTbl)[ nM + 1 ]->End() &&
2060 528 : ( nsRedlineType_t::REDLINE_INSERT == (*mpRedlineTbl)[ nM + 1 ]->GetType() ) )
2061 : {
2062 0 : ++nM;
2063 0 : pRedl = (*mpRedlineTbl)[ nM ];
2064 : }
2065 : }
2066 :
2067 1277 : if( pFndPos )
2068 1277 : *pFndPos = nM;
2069 1277 : return pRedl;
2070 : }
2071 39565 : else if( *pEnd <= rPos )
2072 38159 : nU = nM + 1;
2073 1406 : else if( nM == 0 )
2074 : {
2075 577 : if( pFndPos )
2076 573 : *pFndPos = nU;
2077 577 : return 0;
2078 : }
2079 : else
2080 829 : nO = nM - 1;
2081 : }
2082 : }
2083 14314 : if( pFndPos )
2084 13044 : *pFndPos = nU;
2085 14314 : return 0;
2086 :
2087 : // #TODO - add 'SwExtraRedlineTbl' also ?
2088 : }
2089 :
2090 0 : bool DocumentRedlineManager::AcceptRedline( sal_uInt16 nPos, bool bCallDelete )
2091 : {
2092 0 : bool bRet = false;
2093 :
2094 : // Switch to visible in any case
2095 0 : if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
2096 0 : (nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) )
2097 0 : SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | meRedlineMode));
2098 :
2099 0 : SwRangeRedline* pTmp = (*mpRedlineTbl)[ nPos ];
2100 0 : if( pTmp->HasMark() && pTmp->IsVisible() )
2101 : {
2102 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2103 : {
2104 0 : SwRewriter aRewriter;
2105 :
2106 0 : aRewriter.AddRule(UndoArg1, pTmp->GetDescr());
2107 0 : m_rSwdoc.GetIDocumentUndoRedo().StartUndo(UNDO_ACCEPT_REDLINE, &aRewriter);
2108 : }
2109 :
2110 0 : int nLoopCnt = 2;
2111 0 : sal_uInt16 nSeqNo = pTmp->GetSeqNo();
2112 :
2113 0 : do {
2114 :
2115 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2116 : {
2117 0 : SwUndo *const pUndo( new SwUndoAcceptRedline(*pTmp) );
2118 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
2119 : }
2120 :
2121 0 : bRet |= lcl_AcceptRedline( *mpRedlineTbl, nPos, bCallDelete );
2122 :
2123 0 : if( nSeqNo )
2124 : {
2125 0 : if( USHRT_MAX == nPos )
2126 0 : nPos = 0;
2127 : sal_uInt16 nFndPos = 2 == nLoopCnt
2128 0 : ? mpRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
2129 0 : : mpRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
2130 0 : if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
2131 : USHRT_MAX != ( nFndPos =
2132 0 : mpRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
2133 0 : pTmp = (*mpRedlineTbl)[ nPos = nFndPos ];
2134 : else
2135 0 : nLoopCnt = 0;
2136 : }
2137 : else
2138 0 : nLoopCnt = 0;
2139 :
2140 : } while( nLoopCnt );
2141 :
2142 0 : if( bRet )
2143 : {
2144 0 : CompressRedlines();
2145 0 : m_rSwdoc.getIDocumentState().SetModified();
2146 : }
2147 :
2148 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2149 : {
2150 0 : m_rSwdoc.GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
2151 : }
2152 : }
2153 0 : return bRet;
2154 :
2155 : // #TODO - add 'SwExtraRedlineTbl' also ?
2156 : }
2157 :
2158 0 : bool DocumentRedlineManager::AcceptRedline( const SwPaM& rPam, bool bCallDelete )
2159 : {
2160 : // Switch to visible in any case
2161 0 : if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
2162 0 : (nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) )
2163 0 : SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | meRedlineMode));
2164 :
2165 : // The Selection is only in the ContentSection. If there are Redlines
2166 : // to Non-ContentNodes before or after that, then the Selections
2167 : // expand to them.
2168 0 : SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2169 0 : lcl_AdjustRedlineRange( aPam );
2170 :
2171 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2172 : {
2173 0 : m_rSwdoc.GetIDocumentUndoRedo().StartUndo( UNDO_ACCEPT_REDLINE, NULL );
2174 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( new SwUndoAcceptRedline( aPam ));
2175 : }
2176 :
2177 : int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *mpRedlineTbl,
2178 0 : bCallDelete, aPam );
2179 0 : if( nRet > 0 )
2180 : {
2181 0 : CompressRedlines();
2182 0 : m_rSwdoc.getIDocumentState().SetModified();
2183 : }
2184 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2185 : {
2186 0 : OUString aTmpStr;
2187 :
2188 : {
2189 0 : SwRewriter aRewriter;
2190 0 : aRewriter.AddRule(UndoArg1, OUString::number(nRet));
2191 0 : aTmpStr = aRewriter.Apply(OUString(SW_RES(STR_N_REDLINES)));
2192 : }
2193 :
2194 0 : SwRewriter aRewriter;
2195 0 : aRewriter.AddRule(UndoArg1, aTmpStr);
2196 :
2197 0 : m_rSwdoc.GetIDocumentUndoRedo().EndUndo( UNDO_ACCEPT_REDLINE, &aRewriter );
2198 : }
2199 0 : return nRet != 0;
2200 :
2201 : // #TODO - add 'SwExtraRedlineTbl' also ?
2202 : }
2203 :
2204 0 : bool DocumentRedlineManager::RejectRedline( sal_uInt16 nPos, bool bCallDelete )
2205 : {
2206 0 : bool bRet = false;
2207 :
2208 : // Switch to visible in any case
2209 0 : if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
2210 0 : (nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) )
2211 0 : SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | meRedlineMode));
2212 :
2213 0 : SwRangeRedline* pTmp = (*mpRedlineTbl)[ nPos ];
2214 0 : if( pTmp->HasMark() && pTmp->IsVisible() )
2215 : {
2216 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2217 : {
2218 0 : SwRewriter aRewriter;
2219 :
2220 0 : aRewriter.AddRule(UndoArg1, pTmp->GetDescr());
2221 0 : m_rSwdoc.GetIDocumentUndoRedo().StartUndo(UNDO_REJECT_REDLINE, &aRewriter);
2222 : }
2223 :
2224 0 : int nLoopCnt = 2;
2225 0 : sal_uInt16 nSeqNo = pTmp->GetSeqNo();
2226 :
2227 0 : do {
2228 :
2229 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2230 : {
2231 0 : SwUndo *const pUndo( new SwUndoRejectRedline( *pTmp ) );
2232 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo(pUndo);
2233 : }
2234 :
2235 0 : bRet |= lcl_RejectRedline( *mpRedlineTbl, nPos, bCallDelete );
2236 :
2237 0 : if( nSeqNo )
2238 : {
2239 0 : if( USHRT_MAX == nPos )
2240 0 : nPos = 0;
2241 : sal_uInt16 nFndPos = 2 == nLoopCnt
2242 0 : ? mpRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
2243 0 : : mpRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
2244 0 : if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
2245 : USHRT_MAX != ( nFndPos =
2246 0 : mpRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
2247 0 : pTmp = (*mpRedlineTbl)[ nPos = nFndPos ];
2248 : else
2249 0 : nLoopCnt = 0;
2250 : }
2251 : else
2252 0 : nLoopCnt = 0;
2253 :
2254 : } while( nLoopCnt );
2255 :
2256 0 : if( bRet )
2257 : {
2258 0 : CompressRedlines();
2259 0 : m_rSwdoc.getIDocumentState().SetModified();
2260 : }
2261 :
2262 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2263 : {
2264 0 : m_rSwdoc.GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
2265 : }
2266 : }
2267 0 : return bRet;
2268 :
2269 : // #TODO - add 'SwExtraRedlineTbl' also ?
2270 : }
2271 :
2272 0 : bool DocumentRedlineManager::RejectRedline( const SwPaM& rPam, bool bCallDelete )
2273 : {
2274 : // Switch to visible in any case
2275 0 : if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
2276 0 : (nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) )
2277 0 : SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | meRedlineMode));
2278 :
2279 : // The Selection is only in the ContentSection. If there are Redlines
2280 : // to Non-ContentNodes before or after that, then the Selections
2281 : // expand to them.
2282 0 : SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
2283 0 : lcl_AdjustRedlineRange( aPam );
2284 :
2285 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2286 : {
2287 0 : m_rSwdoc.GetIDocumentUndoRedo().StartUndo( UNDO_REJECT_REDLINE, NULL );
2288 0 : m_rSwdoc.GetIDocumentUndoRedo().AppendUndo( new SwUndoRejectRedline(aPam) );
2289 : }
2290 :
2291 : int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *mpRedlineTbl,
2292 0 : bCallDelete, aPam );
2293 0 : if( nRet > 0 )
2294 : {
2295 0 : CompressRedlines();
2296 0 : m_rSwdoc.getIDocumentState().SetModified();
2297 : }
2298 0 : if (m_rSwdoc.GetIDocumentUndoRedo().DoesUndo())
2299 : {
2300 0 : OUString aTmpStr;
2301 :
2302 : {
2303 0 : SwRewriter aRewriter;
2304 0 : aRewriter.AddRule(UndoArg1, OUString::number(nRet));
2305 0 : aTmpStr = aRewriter.Apply(OUString(SW_RES(STR_N_REDLINES)));
2306 : }
2307 :
2308 0 : SwRewriter aRewriter;
2309 0 : aRewriter.AddRule(UndoArg1, aTmpStr);
2310 :
2311 0 : m_rSwdoc.GetIDocumentUndoRedo().EndUndo( UNDO_REJECT_REDLINE, &aRewriter );
2312 : }
2313 :
2314 0 : return nRet != 0;
2315 :
2316 : // #TODO - add 'SwExtraRedlineTbl' also ?
2317 : }
2318 :
2319 0 : const SwRangeRedline* DocumentRedlineManager::SelNextRedline( SwPaM& rPam ) const
2320 : {
2321 0 : rPam.DeleteMark();
2322 0 : rPam.SetMark();
2323 :
2324 0 : SwPosition& rSttPos = *rPam.GetPoint();
2325 0 : SwPosition aSavePos( rSttPos );
2326 : bool bRestart;
2327 :
2328 : // If the starting position points to the last valid ContentNode,
2329 : // we take the next Redline in any case.
2330 0 : sal_uInt16 n = 0;
2331 0 : const SwRangeRedline* pFnd = GetRedlineTbl().FindAtPosition( rSttPos, n, true );
2332 0 : if( pFnd )
2333 : {
2334 0 : const SwPosition* pEnd = pFnd->End();
2335 0 : if( !pEnd->nNode.GetNode().IsCntntNode() )
2336 : {
2337 0 : SwNodeIndex aTmp( pEnd->nNode );
2338 0 : SwCntntNode* pCNd = m_rSwdoc.GetNodes().GoPrevSection( &aTmp );
2339 0 : if( !pCNd || ( aTmp == rSttPos.nNode &&
2340 0 : pCNd->Len() == rSttPos.nContent.GetIndex() ))
2341 0 : pFnd = 0;
2342 : }
2343 0 : if( pFnd )
2344 0 : rSttPos = *pFnd->End();
2345 : }
2346 :
2347 0 : do {
2348 0 : bRestart = false;
2349 :
2350 0 : for( ; !pFnd && n < mpRedlineTbl->size(); ++n )
2351 : {
2352 0 : pFnd = (*mpRedlineTbl)[ n ];
2353 0 : if( pFnd->HasMark() && pFnd->IsVisible() )
2354 : {
2355 0 : *rPam.GetMark() = *pFnd->Start();
2356 0 : rSttPos = *pFnd->End();
2357 0 : break;
2358 : }
2359 : else
2360 0 : pFnd = 0;
2361 : }
2362 :
2363 0 : if( pFnd )
2364 : {
2365 : // Merge all of the same type and author that are
2366 : // consecutive into one Selection.
2367 0 : const SwPosition* pPrevEnd = pFnd->End();
2368 0 : while( ++n < mpRedlineTbl->size() )
2369 : {
2370 0 : const SwRangeRedline* pTmp = (*mpRedlineTbl)[ n ];
2371 0 : if( pTmp->HasMark() && pTmp->IsVisible() )
2372 : {
2373 : const SwPosition *pRStt;
2374 0 : if( pFnd->GetType() == pTmp->GetType() &&
2375 0 : pFnd->GetAuthor() == pTmp->GetAuthor() &&
2376 0 : ( *pPrevEnd == *( pRStt = pTmp->Start() ) ||
2377 0 : IsPrevPos( *pPrevEnd, *pRStt )) )
2378 : {
2379 0 : pPrevEnd = pTmp->End();
2380 0 : rSttPos = *pPrevEnd;
2381 : }
2382 : else
2383 0 : break;
2384 : }
2385 : }
2386 : }
2387 :
2388 0 : if( pFnd )
2389 : {
2390 0 : const SwRangeRedline* pSaveFnd = pFnd;
2391 :
2392 : SwCntntNode* pCNd;
2393 0 : SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
2394 0 : if( !pIdx->GetNode().IsCntntNode() &&
2395 0 : 0 != ( pCNd = m_rSwdoc.GetNodes().GoNextSection( pIdx )) )
2396 : {
2397 0 : if( *pIdx <= rPam.GetPoint()->nNode )
2398 0 : rPam.GetMark()->nContent.Assign( pCNd, 0 );
2399 : else
2400 0 : pFnd = 0;
2401 : }
2402 :
2403 0 : if( pFnd )
2404 : {
2405 0 : pIdx = &rPam.GetPoint()->nNode;
2406 0 : if( !pIdx->GetNode().IsCntntNode() &&
2407 0 : 0 != ( pCNd = m_rSwdoc.GetNodes().GoPrevSection( pIdx )) )
2408 : {
2409 0 : if( *pIdx >= rPam.GetMark()->nNode )
2410 0 : rPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
2411 : else
2412 0 : pFnd = 0;
2413 : }
2414 : }
2415 :
2416 0 : if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
2417 : {
2418 0 : if( n < mpRedlineTbl->size() )
2419 : {
2420 0 : bRestart = true;
2421 0 : *rPam.GetPoint() = *pSaveFnd->End();
2422 : }
2423 : else
2424 : {
2425 0 : rPam.DeleteMark();
2426 0 : *rPam.GetPoint() = aSavePos;
2427 : }
2428 0 : pFnd = 0;
2429 : }
2430 : }
2431 : } while( bRestart );
2432 :
2433 0 : return pFnd;
2434 :
2435 : // #TODO - add 'SwExtraRedlineTbl' also ?
2436 : }
2437 :
2438 0 : const SwRangeRedline* DocumentRedlineManager::SelPrevRedline( SwPaM& rPam ) const
2439 : {
2440 0 : rPam.DeleteMark();
2441 0 : rPam.SetMark();
2442 :
2443 0 : SwPosition& rSttPos = *rPam.GetPoint();
2444 0 : SwPosition aSavePos( rSttPos );
2445 : bool bRestart;
2446 :
2447 : // If the starting position points to the last valid ContentNode,
2448 : // we take the previous Redline in any case.
2449 0 : sal_uInt16 n = 0;
2450 0 : const SwRangeRedline* pFnd = GetRedlineTbl().FindAtPosition( rSttPos, n, false );
2451 0 : if( pFnd )
2452 : {
2453 0 : const SwPosition* pStt = pFnd->Start();
2454 0 : if( !pStt->nNode.GetNode().IsCntntNode() )
2455 : {
2456 0 : SwNodeIndex aTmp( pStt->nNode );
2457 0 : SwCntntNode* pCNd = m_rSwdoc.GetNodes().GoNextSection( &aTmp );
2458 0 : if( !pCNd || ( aTmp == rSttPos.nNode &&
2459 0 : !rSttPos.nContent.GetIndex() ))
2460 0 : pFnd = 0;
2461 : }
2462 0 : if( pFnd )
2463 0 : rSttPos = *pFnd->Start();
2464 : }
2465 :
2466 0 : do {
2467 0 : bRestart = false;
2468 :
2469 0 : while( !pFnd && 0 < n )
2470 : {
2471 0 : pFnd = (*mpRedlineTbl)[ --n ];
2472 0 : if( pFnd->HasMark() && pFnd->IsVisible() )
2473 : {
2474 0 : *rPam.GetMark() = *pFnd->End();
2475 0 : rSttPos = *pFnd->Start();
2476 : }
2477 : else
2478 0 : pFnd = 0;
2479 : }
2480 :
2481 0 : if( pFnd )
2482 : {
2483 : // Merge all of the same type and author that are
2484 : // consecutive into one Selection.
2485 0 : const SwPosition* pNextStt = pFnd->Start();
2486 0 : while( 0 < n )
2487 : {
2488 0 : const SwRangeRedline* pTmp = (*mpRedlineTbl)[ --n ];
2489 0 : if( pTmp->HasMark() && pTmp->IsVisible() )
2490 : {
2491 : const SwPosition *pREnd;
2492 0 : if( pFnd->GetType() == pTmp->GetType() &&
2493 0 : pFnd->GetAuthor() == pTmp->GetAuthor() &&
2494 0 : ( *pNextStt == *( pREnd = pTmp->End() ) ||
2495 0 : IsPrevPos( *pREnd, *pNextStt )) )
2496 : {
2497 0 : pNextStt = pTmp->Start();
2498 0 : rSttPos = *pNextStt;
2499 : }
2500 : else
2501 : {
2502 0 : ++n;
2503 0 : break;
2504 : }
2505 : }
2506 : }
2507 : }
2508 :
2509 0 : if( pFnd )
2510 : {
2511 0 : const SwRangeRedline* pSaveFnd = pFnd;
2512 :
2513 : SwCntntNode* pCNd;
2514 0 : SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
2515 0 : if( !pIdx->GetNode().IsCntntNode() &&
2516 0 : 0 != ( pCNd = m_rSwdoc.GetNodes().GoPrevSection( pIdx )) )
2517 : {
2518 0 : if( *pIdx >= rPam.GetPoint()->nNode )
2519 0 : rPam.GetMark()->nContent.Assign( pCNd, pCNd->Len() );
2520 : else
2521 0 : pFnd = 0;
2522 : }
2523 :
2524 0 : if( pFnd )
2525 : {
2526 0 : pIdx = &rPam.GetPoint()->nNode;
2527 0 : if( !pIdx->GetNode().IsCntntNode() &&
2528 0 : 0 != ( pCNd = m_rSwdoc.GetNodes().GoNextSection( pIdx )) )
2529 : {
2530 0 : if( *pIdx <= rPam.GetMark()->nNode )
2531 0 : rPam.GetPoint()->nContent.Assign( pCNd, 0 );
2532 : else
2533 0 : pFnd = 0;
2534 : }
2535 : }
2536 :
2537 0 : if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
2538 : {
2539 0 : if( n )
2540 : {
2541 0 : bRestart = true;
2542 0 : *rPam.GetPoint() = *pSaveFnd->Start();
2543 : }
2544 : else
2545 : {
2546 0 : rPam.DeleteMark();
2547 0 : *rPam.GetPoint() = aSavePos;
2548 : }
2549 0 : pFnd = 0;
2550 : }
2551 : }
2552 : } while( bRestart );
2553 :
2554 0 : return pFnd;
2555 :
2556 : // #TODO - add 'SwExtraRedlineTbl' also ?
2557 : }
2558 :
2559 : // Set comment at the Redline
2560 0 : bool DocumentRedlineManager::SetRedlineComment( const SwPaM& rPaM, const OUString& rS )
2561 : {
2562 0 : bool bRet = false;
2563 0 : const SwPosition* pStt = rPaM.Start(),
2564 0 : * pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
2565 0 : : rPaM.GetPoint();
2566 0 : sal_uInt16 n = 0;
2567 0 : if( GetRedlineTbl().FindAtPosition( *pStt, n, true ) )
2568 : {
2569 0 : for( ; n < mpRedlineTbl->size(); ++n )
2570 : {
2571 0 : bRet = true;
2572 0 : SwRangeRedline* pTmp = (*mpRedlineTbl)[ n ];
2573 0 : if( pStt != pEnd && *pTmp->Start() > *pEnd )
2574 0 : break;
2575 :
2576 0 : pTmp->SetComment( rS );
2577 0 : if( *pTmp->End() >= *pEnd )
2578 0 : break;
2579 : }
2580 : }
2581 0 : if( bRet )
2582 0 : m_rSwdoc.getIDocumentState().SetModified();
2583 :
2584 0 : return bRet;
2585 :
2586 : // #TODO - add 'SwExtraRedlineTbl' also ?
2587 : }
2588 :
2589 : // Create a new author if necessary
2590 2164 : sal_uInt16 DocumentRedlineManager::GetRedlineAuthor()
2591 : {
2592 2164 : return SW_MOD()->GetRedlineAuthor();
2593 : }
2594 :
2595 : /// Insert new author into the Table for the Readers etc.
2596 5704 : sal_uInt16 DocumentRedlineManager::InsertRedlineAuthor( const OUString& rNew )
2597 : {
2598 5704 : return SW_MOD()->InsertRedlineAuthor(rNew);
2599 : }
2600 :
2601 0 : void DocumentRedlineManager::UpdateRedlineAttr()
2602 : {
2603 0 : const SwRedlineTbl& rTbl = GetRedlineTbl();
2604 0 : for( sal_uInt16 n = 0; n < rTbl.size(); ++n )
2605 : {
2606 0 : SwRangeRedline* pRedl = rTbl[ n ];
2607 0 : if( pRedl->IsVisible() )
2608 0 : pRedl->InvalidateRange();
2609 : }
2610 :
2611 : // #TODO - add 'SwExtraRedlineTbl' also ?
2612 0 : }
2613 :
2614 524 : const uno::Sequence <sal_Int8>& DocumentRedlineManager::GetRedlinePassword() const
2615 : {
2616 524 : return maRedlinePasswd;
2617 : }
2618 :
2619 432 : void DocumentRedlineManager::SetRedlinePassword(
2620 : /*[in]*/const uno::Sequence <sal_Int8>& rNewPassword)
2621 : {
2622 432 : maRedlinePasswd = rNewPassword;
2623 432 : m_rSwdoc.getIDocumentState().SetModified();
2624 432 : }
2625 :
2626 : /// Set comment text for the Redline, which is inserted later on via
2627 : /// AppendRedline. Is used by Autoformat.
2628 : /// A null pointer resets the mode. The pointer is not copied, so it
2629 : /// needs to stay valid!
2630 0 : void DocumentRedlineManager::SetAutoFmtRedlineComment( const OUString* pTxt, sal_uInt16 nSeqNo )
2631 : {
2632 0 : m_rSwdoc.SetAutoFmtRedline( 0 != pTxt );
2633 0 : if( pTxt )
2634 : {
2635 0 : if( !mpAutoFmtRedlnComment )
2636 0 : mpAutoFmtRedlnComment = new OUString( *pTxt );
2637 : else
2638 0 : *mpAutoFmtRedlnComment = *pTxt;
2639 : }
2640 : else
2641 0 : delete mpAutoFmtRedlnComment, mpAutoFmtRedlnComment = 0;
2642 :
2643 0 : mnAutoFmtRedlnCommentNo = nSeqNo;
2644 0 : }
2645 :
2646 : #define MAX_REDLINE_COUNT 250
2647 :
2648 455 : void DocumentRedlineManager::checkRedlining(RedlineMode_t& _rReadlineMode)
2649 : {
2650 455 : const SwRedlineTbl& rRedlineTbl = GetRedlineTbl();
2651 455 : SwEditShell* pEditShell = m_rSwdoc.GetEditShell();
2652 455 : vcl::Window* pParent = pEditShell ? pEditShell->GetWin() : NULL;
2653 455 : if ( pParent && !mbReadlineChecked && rRedlineTbl.size() > MAX_REDLINE_COUNT
2654 455 : && !((_rReadlineMode & nsRedlineMode_t::REDLINE_SHOW_DELETE) == nsRedlineMode_t::REDLINE_SHOW_DELETE) )
2655 : {
2656 0 : MessageDialog aQuery(pParent, "QueryShowChangesDialog", "modules/swriter/ui/queryshowchangesdialog.ui");
2657 0 : sal_uInt16 nResult = aQuery.Execute();
2658 0 : mbReadlineChecked = true;
2659 0 : if ( nResult == RET_YES )
2660 : {
2661 0 : sal_Int32 nMode = (sal_Int32)_rReadlineMode;
2662 0 : nMode |= nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE;
2663 0 : _rReadlineMode = (RedlineMode_t)nMode;
2664 0 : }
2665 : }
2666 455 : }
2667 :
2668 15135 : DocumentRedlineManager::~DocumentRedlineManager()
2669 : {
2670 5045 : delete mpRedlineTbl; mpRedlineTbl = 0;
2671 5045 : delete mpExtraRedlineTbl; mpExtraRedlineTbl = 0;
2672 5045 : delete mpAutoFmtRedlnComment; mpAutoFmtRedlnComment = 0;
2673 10090 : }
2674 :
2675 270 : }
2676 :
2677 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|