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