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