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