summaryrefslogtreecommitdiff
path: root/sw/source/core/doc/docredln.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/doc/docredln.cxx')
-rw-r--r--sw/source/core/doc/docredln.cxx3868
1 files changed, 3868 insertions, 0 deletions
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
new file mode 100644
index 000000000000..b46cf1e101c0
--- /dev/null
+++ b/sw/source/core/doc/docredln.cxx
@@ -0,0 +1,3868 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+#include <tools/shl.hxx>
+#include <svl/itemiter.hxx>
+#include <sfx2/app.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <swmodule.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <redline.hxx>
+#include <swundo.hxx>
+#include <UndoCore.hxx>
+#include <UndoRedline.hxx>
+#include <hints.hxx>
+#include <pamtyp.hxx>
+#include <poolfmt.hxx>
+#include <viewsh.hxx>
+#include <rootfrm.hxx>
+
+#include <comcore.hrc>
+
+using namespace com::sun::star;
+
+TYPEINIT1(SwRedlineHint, SfxHint);
+
+#ifndef DBG_UTIL
+
+ #define _CHECK_REDLINE( pDoc )
+ #define _DEBUG_REDLINE( pDoc )
+
+#else
+
+#define _ERROR_PREFIX "redline table corrupted: "
+
+ // helper function for lcl_CheckRedline
+ // 1. make sure that pPos->nContent points into pPos->nNode
+ // (or into the 'special' no-content-node-IndexReg)
+ // 2. check that position is valid and doesn't point behind text
+ void lcl_CheckPosition( const SwPosition* pPos )
+ {
+ SwPosition aComparePos( *pPos );
+ aComparePos.nContent.Assign(
+ aComparePos.nNode.GetNode().GetCntntNode(), 0 );
+ DBG_ASSERT( pPos->nContent.GetIdxReg() ==
+ aComparePos.nContent.GetIdxReg(),
+ _ERROR_PREFIX "illegal position" );
+
+ SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ DBG_ASSERT( pPos->nContent == 0,
+ _ERROR_PREFIX "non-text-node with content" );
+ }
+ else
+ {
+ DBG_ASSERT( pPos->nContent >= 0 &&
+ pPos->nContent <= pTxtNode->Len(),
+ _ERROR_PREFIX "index behind text" );
+ }
+ }
+
+ void lcl_CheckPam( const SwPaM* pPam )
+ {
+ DBG_ASSERT( pPam != NULL, _ERROR_PREFIX "illegal argument" );
+ lcl_CheckPosition( pPam->GetPoint() );
+ lcl_CheckPosition( pPam->GetMark() );
+ }
+
+ // check validity of the redline table. Checks redline bounds, and make
+ // sure the redlines are sorted and non-overlapping.
+ void lcl_CheckRedline( const SwDoc* pDoc )
+ {
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+
+ // verify valid redline positions
+ for( sal_uInt16 i = 0; i < rTbl.Count(); ++i )
+ lcl_CheckPam( rTbl[ i ] );
+
+ for( sal_uInt16 j = 0; j < rTbl.Count(); ++j )
+ {
+ // check for empty redlines
+ DBG_ASSERT( ( *(rTbl[j]->GetPoint()) != *(rTbl[j]->GetMark()) ) ||
+ ( rTbl[j]->GetContentIdx() != NULL ),
+ _ERROR_PREFIX "empty redline" );
+ }
+
+ // verify proper redline sorting
+ for( sal_uInt16 n = 1; n < rTbl.Count(); ++n )
+ {
+ const SwRedline* pPrev = rTbl[ n-1 ];
+ const SwRedline* pCurrent = rTbl[ n ];
+
+ // check redline sorting
+ DBG_ASSERT( *pPrev->Start() <= *pCurrent->Start(),
+ _ERROR_PREFIX "not sorted correctly" );
+
+ // check for overlapping redlines
+ DBG_ASSERT( *pPrev->End() <= *pCurrent->Start(),
+ _ERROR_PREFIX "overlapping redlines" );
+ }
+ }
+
+ #define _CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc );
+
+ void lcl_DebugRedline( const SwDoc* pDoc )
+ {
+ static sal_uInt16 nWatch = 0;
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ sal_uInt16 nDummy = 0;
+ const SwRedline* pCurrent = rTbl[ n ];
+ const SwRedline* pNext = n+1 < rTbl.Count() ? rTbl[ n+1 ] : 0;
+ if( pCurrent == pNext )
+ ++nDummy;
+ if( n == nWatch )
+ ++nDummy; // Possible debugger breakpoint
+ }
+ }
+
+ #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
+
+#endif
+
+SV_IMPL_OP_PTRARR_SORT( _SwRedlineTbl, SwRedlinePtr )
+
+RedlineMode_t SwDoc::GetRedlineMode() const
+{
+ return eRedlineMode;
+}
+
+void SwDoc::SetRedlineMode( RedlineMode_t eMode )
+{
+ if( eRedlineMode != eMode )
+ {
+ if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode)
+ || 0 == (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) )
+ {
+ bool bSaveInXMLImportFlag = IsInXMLImport();
+ SetInXMLImport( false );
+ // und dann alles verstecken, anzeigen
+ void (SwRedline::*pFnc)( sal_uInt16 ) = 0;
+
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE :
+ pFnc = &SwRedline::Show;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ pFnc = &SwRedline::Hide;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ pFnc = &SwRedline::ShowOriginal;
+ break;
+
+ default:
+ pFnc = &SwRedline::Hide;
+ eMode = (RedlineMode_t)(eMode | nsRedlineMode_t::REDLINE_SHOW_INSERT);
+ break;
+ }
+
+ _CHECK_REDLINE( this )
+
+ if( pFnc )
+ for( sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop )
+ for( sal_uInt16 i = 0; i < pRedlineTbl->Count(); ++i )
+ ((*pRedlineTbl)[ i ]->*pFnc)( nLoop );
+ _CHECK_REDLINE( this )
+ SetInXMLImport( bSaveInXMLImportFlag );
+ }
+ eRedlineMode = eMode;
+ SetModified();
+ }
+}
+
+bool SwDoc::IsRedlineOn() const
+{
+ return IDocumentRedlineAccess::IsRedlineOn(eRedlineMode);
+}
+
+bool SwDoc::IsIgnoreRedline() const
+{
+ return (nsRedlineMode_t::REDLINE_IGNORE & eRedlineMode);
+}
+
+void SwDoc::SetRedlineMode_intern(RedlineMode_t eMode)
+{
+ eRedlineMode = eMode;
+}
+
+const SwRedlineTbl& SwDoc::GetRedlineTbl() const
+{
+ return *pRedlineTbl;
+}
+
+bool SwDoc::IsRedlineMove() const
+{
+ return mbIsRedlineMove;
+}
+
+void SwDoc::SetRedlineMove(bool bFlag)
+{
+ mbIsRedlineMove = bFlag;
+}
+
+const uno::Sequence <sal_Int8>& SwDoc::GetRedlinePassword() const
+{
+ return aRedlinePasswd;
+}
+
+inline bool IsPrevPos( const SwPosition rPos1, const SwPosition rPos2 )
+{
+ const SwCntntNode* pCNd;
+ return 0 == rPos2.nContent.GetIndex() &&
+ rPos2.nNode.GetIndex() - 1 == rPos1.nNode.GetIndex() &&
+ 0 != ( pCNd = rPos1.nNode.GetNode().GetCntntNode() )
+ ? rPos1.nContent.GetIndex() == pCNd->Len()
+ : false;
+}
+
+#ifdef DEBUG
+bool CheckPosition( const SwPosition* pStt, const SwPosition* pEnd )
+{
+ int nError = 0;
+ SwNode* pSttNode = &pStt->nNode.GetNode();
+ SwNode* pEndNode = &pEnd->nNode.GetNode();
+ SwNode* pSttTab = pSttNode->StartOfSectionNode()->FindTableNode();
+ SwNode* pEndTab = pEndNode->StartOfSectionNode()->FindTableNode();
+ SwNode* pSttStart = pSttNode;
+ while( pSttStart && (!pSttStart->IsStartNode() || pSttStart->IsSectionNode() ||
+ pSttStart->IsTableNode() ) )
+ pSttStart = pSttStart->StartOfSectionNode();
+ SwNode* pEndStart = pEndNode;
+ while( pEndStart && (!pEndStart->IsStartNode() || pEndStart->IsSectionNode() ||
+ pEndStart->IsTableNode() ) )
+ pEndStart = pEndStart->StartOfSectionNode();
+ if( pSttTab != pEndTab )
+ nError = 1;
+ if( !pSttTab && pSttStart != pEndStart )
+ nError |= 2;
+ if( nError )
+ nError += 10;
+ return nError != 0;
+}
+#endif
+
+/*
+
+Text heisst, nicht von Redline "verseuchter" Text.
+
+Verhalten von Insert-Redline:
+ - im Text - Redline Object einfuegen
+ - im InsertRedline (eigenes) - ignorieren, bestehendes wird
+ aufgespannt
+ - im InsertRedline (andere) - Insert Redline aufsplitten
+ Redline Object einfuegen
+ - in DeleteRedline - Delete Redline aufsplitten oder
+ am Ende/Anfang verschieben
+
+Verhalten von Delete-Redline:
+ - im Text - Redline Object einfuegen
+ - im DeleteRedline (eigenes/andere) - ignorieren
+ - im InsertRedline (eigenes) - ignorieren, Zeichen aber loeschen
+ - im InsertRedline (andere) - Insert Redline aufsplitten
+ Redline Object einfuegen
+ - Ueberlappung von Text und - Text in eigenen Insert loeschen,
+ eigenem Insert im andereren Text aufspannen (bis
+ zum Insert!
+ - Ueberlappung von Text und - Redline Object einfuegen, der
+ anderem Insert andere Insert wird vom Delete
+ ueberlappt
+*/
+
+bool SwDoc::AppendRedline( SwRedline* pNewRedl, bool bCallDelete )
+{
+#if 0
+// #i93179# disabled: ASSERT in ~SwIndexReg #ifdef DBG_UTIL
+ SwRedline aCopy( *pNewRedl );
+#endif
+ bool bError = true;
+ _CHECK_REDLINE( this )
+
+ if( IsRedlineOn() && !IsShowOriginal( eRedlineMode ) &&
+ pNewRedl->GetAuthorString().Len() )
+ {
+ pNewRedl->InvalidateRange();
+
+ if( mbIsAutoFmtRedline )
+ {
+ pNewRedl->SetAutoFmtFlag();
+ if( pAutoFmtRedlnComment && pAutoFmtRedlnComment->Len() )
+ {
+ pNewRedl->SetComment( *pAutoFmtRedlnComment );
+ pNewRedl->SetSeqNo( nAutoFmtRedlnCommentNo );
+ }
+ }
+
+ SwPosition* pStt = pNewRedl->Start(),
+ * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark()
+ : pNewRedl->GetPoint();
+ {
+ SwTxtNode* pTxtNode = pStt->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ if( pStt->nContent > 0 )
+ {
+ DBG_ASSERT( false, "Redline start: non-text-node with content" );
+ pStt->nContent = 0;
+ }
+ }
+ else
+ {
+ if( pStt->nContent > pTxtNode->Len() )
+ {
+ DBG_ASSERT( false, "Redline start: index behind text" );
+ pStt->nContent = pTxtNode->Len();
+ }
+ }
+ pTxtNode = pEnd->nNode.GetNode().GetTxtNode();
+ if( pTxtNode == NULL )
+ {
+ if( pEnd->nContent > 0 )
+ {
+ DBG_ASSERT( false, "Redline end: non-text-node with content" );
+ pEnd->nContent = 0;
+ }
+ }
+ else
+ {
+ if( pEnd->nContent > pTxtNode->Len() )
+ {
+ DBG_ASSERT( false, "Redline end: index behind text" );
+ pEnd->nContent = pTxtNode->Len();
+ }
+ }
+ }
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ { // Do not insert empty redlines
+ delete pNewRedl;
+ return sal_False;
+ }
+ sal_Bool bCompress = sal_False;
+ sal_uInt16 n = 0;
+ // zur StartPos das erste Redline suchen
+ if( !GetRedline( *pStt, &n ) && n )
+ --n;
+ bool bDec = false;
+
+ for( ; pNewRedl && n < pRedlineTbl->Count(); bDec ? n : ++n )
+ {
+ bDec = false;
+#ifdef DVO_TEST
+ _CHECK_REDLINE( this )
+#endif
+
+ SwRedline* pRedl = (*pRedlineTbl)[ n ];
+ SwPosition* pRStt = pRedl->Start(),
+ * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
+ : pRedl->GetPoint();
+
+ // #i8518# remove empty redlines while we're at it
+ if( ( *pRStt == *pREnd ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy(n);
+ continue;
+ }
+
+ SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
+
+ switch( pNewRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ if( pRedl->IsOwnRedline( *pNewRedl ) )
+ {
+ bool bDelete = false;
+
+ // ggfs. verschmelzen?
+ if( (( POS_BEHIND == eCmpPos &&
+ IsPrevPos( *pREnd, *pStt ) ) ||
+ ( POS_COLLIDE_START == eCmpPos ) ||
+ ( POS_OVERLAP_BEHIND == eCmpPos ) ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ ( n+1 >= pRedlineTbl->Count() ||
+ ( *(*pRedlineTbl)[ n+1 ]->Start() >= *pEnd &&
+ *(*pRedlineTbl)[ n+1 ]->Start() != *pREnd ) ) )
+ {
+ pRedl->SetEnd( *pEnd, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+
+ bError = false;
+ bDelete = true;
+ }
+ else if( (( POS_BEFORE == eCmpPos &&
+ IsPrevPos( *pEnd, *pRStt ) ) ||
+ ( POS_COLLIDE_END == eCmpPos ) ||
+ ( POS_OVERLAP_BEFORE == eCmpPos ) ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ ( !n ||
+ *(*pRedlineTbl)[ n-1 ]->End() != *pRStt ))
+ {
+ pRedl->SetStart( *pStt, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+
+ bError = false;
+ bDelete = true;
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // #107164# own insert-over-insert
+ // redlines: just scrap the inside ones
+ pRedlineTbl->Remove( n );
+ bDec = true;
+ }
+ // <- #107164#
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ {
+ *pStt = *pREnd;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ bDelete = true;
+ }
+ else if( POS_OVERLAP_BEFORE == eCmpPos )
+ {
+ *pEnd = *pRStt;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ bDelete = true;
+ }
+ else if( POS_INSIDE == eCmpPos || POS_EQUAL == eCmpPos)
+ bDelete = true;
+
+ if( bDelete )
+ {
+ delete pNewRedl, pNewRedl = 0;
+ bCompress = sal_True;
+ }
+ }
+ else if( POS_INSIDE == eCmpPos )
+ {
+ // aufsplitten
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ pRedlineTbl->Insert( pCpy );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // #102366# handle overlapping redlines in broken
+ // documents
+
+ // split up the new redline, since it covers the
+ // existing redline. Insert the first part, and
+ // progress with the remainder as usual
+ SwRedline* pSplit = new SwRedline( *pNewRedl );
+ pSplit->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd );
+ pRedlineTbl->Insert( pSplit );
+ if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ else if ( POS_OVERLAP_BEHIND == eCmpPos )
+ {
+ // #107164# handle overlapping redlines in broken
+ // documents
+ pNewRedl->SetStart( *pREnd );
+ }
+ else if ( POS_OVERLAP_BEFORE == eCmpPos )
+ {
+ // #107164# handle overlapping redlines in broken
+ // documents
+ *pEnd = *pRStt;
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ if( POS_INSIDE == eCmpPos )
+ {
+ // aufsplitten
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ pRedlineTbl->Insert( pCpy );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+ }
+ else if ( POS_OUTSIDE == eCmpPos )
+ {
+ // #102366# handle overlapping redlines in broken
+ // documents
+
+ // split up the new redline, since it covers the
+ // existing redline. Insert the first part, and
+ // progress with the remainder as usual
+ SwRedline* pSplit = new SwRedline( *pNewRedl );
+ pSplit->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd );
+ pRedlineTbl->Insert( pSplit );
+ if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
+ {
+ delete pNewRedl;
+ pNewRedl = 0;
+ bCompress = true;
+ }
+ }
+ else if ( POS_EQUAL == eCmpPos )
+ {
+ // #112895# handle identical redlines in broken
+ // documents - delete old (delete) redline
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if ( POS_OVERLAP_BEHIND == eCmpPos )
+ { // Another workaround for broken redlines (#107164#)
+ pNewRedl->SetStart( *pREnd );
+ }
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pStt, pREnd );
+ if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ break;
+
+ case POS_INSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuertzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
+ pRedlineTbl->DeleteAndDestroy( n );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( eCmpPos )
+ {
+ case POS_OUTSIDE:
+ {
+ // ueberlappt den akt. komplett
+ // dann muss der neue gesplittet werden
+ if( *pEnd != *pREnd )
+ {
+ SwRedline* pNew = new SwRedline( *pNewRedl );
+ pNew->SetStart( *pREnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ }
+ break;
+
+ case POS_INSIDE:
+ case POS_EQUAL:
+ delete pNewRedl, pNewRedl = 0;
+ bCompress = sal_True;
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ case POS_OVERLAP_BEHIND:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+// 1 == pRedl->GetStackCount() &&
+ pRedl->CanCombine( *pNewRedl ))
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pREnd, pStt );
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_COLLIDE_START:
+ case POS_COLLIDE_END:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+// 1 == pRedl->GetStackCount() &&
+ pRedl->CanCombine( *pNewRedl ) )
+ {
+ if( IsHideChanges( eRedlineMode ))
+ {
+ // dann erstmal sichtbar machen, bevor
+ // die zusammengefasst werden koennen!
+ // Damit pNew auch beim Verschieben der
+ // Indizies behandelt wird, erstmal
+ // temporaer einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Show();
+ pRedlineTbl->Remove( pRedlineTbl->GetPos(pNewRedl ));
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ }
+
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_COLLIDE_START == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+
+ // delete current (below), and restart process with
+ // previous
+ sal_uInt16 nToBeDeleted = n;
+ bDec = true;
+
+ // #107359# Do it again, Sam!
+ // If you can do it for them, you can do it for me.
+ if( *(pNewRedl->Start()) <= *pREnd )
+ {
+ // Whoooah, we just extended the new 'redline'
+ // beyond previous redlines, so better start
+ // again. Of course this is not supposed to
+ // happen, and in an ideal world it doesn't,
+ // but unfortunately this code is buggy and
+ // totally rotten so it does happen and we
+ // better fix it.
+ n = 0;
+ bDec = true;
+ }
+
+ pRedlineTbl->DeleteAndDestroy( nToBeDeleted );
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_INSERT:
+ {
+ // b62341295: Do not throw away redlines
+ // even if they are not allowed to be combined
+ RedlineMode_t eOld = eRedlineMode;
+ if( !( eOld & nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &&
+ pRedl->IsOwnRedline( *pNewRedl ) )
+ {
+
+// auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig
+// zusammen fasst! Der ShowMode muss erhalten bleiben!
+ eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
+ switch( eCmpPos )
+ {
+ case POS_EQUAL:
+ bCompress = sal_True;
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ // kein break!
+
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ eRedlineMode = (RedlineMode_t)(eRedlineMode | nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES);
+
+ // #98863# DeleteAndJoin does not yield the
+ // desired result if there is no paragraph to
+ // join with, i.e. at the end of the document.
+ // For this case, we completely delete the
+ // paragraphs (if, of course, we also start on
+ // a paragraph boundary).
+ if( (pStt->nContent == 0) &&
+ pEnd->nNode.GetNode().IsEndNode() )
+ {
+ pEnd->nNode--;
+ pEnd->nContent.Assign(
+ pEnd->nNode.GetNode().GetTxtNode(), 0);
+ DelFullPara( *pNewRedl );
+ }
+ else
+ DeleteAndJoin( *pNewRedl );
+
+ bCompress = sal_True;
+ }
+ delete pNewRedl, pNewRedl = 0;
+ break;
+
+ case POS_OUTSIDE:
+ {
+ pRedlineTbl->Remove( n );
+ bDec = true;
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ if( bCallDelete )
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( *pRedl );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ }
+ delete pRedl;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ {
+ SwPaM aPam( *pRStt, *pEnd );
+
+ if( *pEnd == *pREnd )
+ pRedlineTbl->DeleteAndDestroy( n );
+ else
+ {
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+
+ if( bCallDelete )
+ {
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( aPam );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ n = 0; // neu Aufsetzen
+ }
+ bDec = true;
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ {
+ SwPaM aPam( *pStt, *pREnd );
+
+ if( *pStt == *pRStt )
+ {
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+
+ if( bCallDelete )
+ {
+ // damit pNew auch beim Verschieben der Indizies
+ // behandelt wird, erstmal temp. einfuegen
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ DeleteAndJoin( aPam );
+ sal_uInt16 nFnd = pRedlineTbl->GetPos(pNewRedl );
+ if( USHRT_MAX != nFnd )
+ pRedlineTbl->Remove( nFnd );
+ else
+ pNewRedl = 0;
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ eRedlineMode = eOld;
+ }
+ else
+ {
+ // it may be necessary to split the existing redline in
+ // two. In this case, pRedl will be changed to cover
+ // only part of it's former range, and pNew will cover
+ // the remainder.
+ SwRedline* pNew = 0;
+
+ switch( eCmpPos )
+ {
+ case POS_EQUAL:
+ {
+ pRedl->PushData( *pNewRedl );
+ delete pNewRedl, pNewRedl = 0;
+ if( IsHideChanges( eRedlineMode ))
+ pRedl->Hide();
+ bCompress = sal_True;
+ }
+ break;
+
+ case POS_INSIDE:
+ {
+ if( *pRStt == *pStt )
+ {
+ // --> mst 2010-05-17 #i97421#
+ // redline w/out extent loops
+ if (*pStt != *pEnd)
+ // <--
+ {
+ pNewRedl->PushData( *pRedl, sal_False );
+ pRedl->SetStart( *pEnd, pRStt );
+ // re-insert
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ }
+ }
+ else
+ {
+ pNewRedl->PushData( *pRedl, sal_False );
+ if( *pREnd != *pEnd )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ }
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ }
+ }
+ }
+ break;
+
+ case POS_OUTSIDE:
+ {
+ pRedl->PushData( *pNewRedl );
+ if( *pEnd == *pREnd )
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ else
+ {
+ pNew = new SwRedline( *pNewRedl );
+ pNew->SetEnd( *pRStt );
+ pNewRedl->SetStart( *pREnd, pStt );
+ }
+ bCompress = sal_True;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ {
+ if( *pEnd == *pREnd )
+ {
+ pRedl->PushData( *pNewRedl );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ if( IsHideChanges( eRedlineMode ))
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Hide();
+ pRedlineTbl->Remove(
+ pRedlineTbl->GetPos(pNewRedl ));
+ }
+ }
+ else
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PushData( *pNewRedl );
+ pNew->SetEnd( *pEnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ pRedl->SetStart( *pNew->End(), pRStt ) ;
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ bDec = true;
+ }
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ {
+ if( *pStt == *pRStt )
+ {
+ pRedl->PushData( *pNewRedl );
+ pNewRedl->SetStart( *pREnd, pStt );
+ if( IsHideChanges( eRedlineMode ))
+ {
+ pRedlineTbl->SavePtrInArr( pNewRedl );
+ pRedl->Hide();
+ pRedlineTbl->Remove(
+ pRedlineTbl->GetPos(pNewRedl ));
+ }
+ }
+ else
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PushData( *pNewRedl );
+ pNew->SetStart( *pStt );
+ pNewRedl->SetStart( *pREnd, pStt );
+ pRedl->SetEnd( *pNew->Start(), pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ // insert the pNew part (if it exists)
+ if( pNew )
+ {
+ // AppendRedline( pNew, bCallDelete );
+ //sal_Bool bRet =
+ pRedlineTbl->Insert( pNew );
+
+ // pNew must be deleted if Insert() wasn't
+ // successful. But that can't happen, since pNew is
+ // part of the original pRedl redline.
+ // ASSERT( bRet, "Can't insert existing redline?" );
+
+ // restart (now with pRedl being split up)
+ n = 0;
+ bDec = true;
+ }
+ }
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ break;
+
+ case POS_INSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuertzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ if( ( *pStt == *pRStt ) &&
+ ( pRedl->GetContentIdx() == NULL ) )
+ pRedlineTbl->DeleteAndDestroy( n );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pRedl->SetEnd( *pStt, pREnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ case nsRedlineType_t::REDLINE_DELETE:
+ switch( eCmpPos )
+ {
+ case POS_OVERLAP_BEFORE:
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pNewRedl->SetStart( *pREnd, pStt );
+ break;
+
+ case POS_EQUAL:
+ case POS_INSIDE:
+ delete pNewRedl, pNewRedl = 0;
+ break;
+
+ case POS_OUTSIDE:
+ // ueberlappt den akt. komplett, dann muss
+ // der neue gesplittet oder verkuerzt werden
+ if( *pEnd != *pREnd )
+ {
+ if( *pEnd != *pRStt )
+ {
+ SwRedline* pNew = new SwRedline( *pNewRedl );
+ pNew->SetStart( *pREnd );
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ }
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+ default:
+ break;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_FORMAT:
+ switch( eCmpPos )
+ {
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ // ueberlappt den akt. komplett oder hat gleiche
+ // Ausdehnung, dann muss der alte geloescht werden
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+
+ case POS_INSIDE:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ))
+ // ein eigenes kann komplett ignoriert werden
+ delete pNewRedl, pNewRedl = 0;
+
+ else if( *pREnd == *pEnd )
+ // ansonsten nur den akt. verkuerzen
+ pRedl->SetEnd( *pStt, pREnd );
+ else if( *pRStt == *pStt )
+ {
+ // ansonsten nur den akt. verkuerzen
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl, n );
+ bDec = true;
+ }
+ else
+ {
+ // liegt komplett im akt.
+ // dann muss der gesplittet werden
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEnd );
+ pRedl->SetEnd( *pStt, pREnd );
+ AppendRedline( pNew, bCallDelete );
+ n = 0; // neu Aufsetzen
+ bDec = true;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ case POS_OVERLAP_BEHIND:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ))
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pRStt, pStt );
+ else
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = 0;
+ }
+ else if( POS_OVERLAP_BEHIND == eCmpPos )
+ pNewRedl->SetStart( *pREnd, pStt );
+ else
+ pNewRedl->SetEnd( *pRStt, pEnd );
+ break;
+
+ case POS_COLLIDE_END:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ) && n &&
+ *(*pRedlineTbl)[ n-1 ]->End() < *pStt )
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ pNewRedl->SetEnd( *pREnd, pEnd );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+ case POS_COLLIDE_START:
+ if( pRedl->IsOwnRedline( *pNewRedl ) &&
+ pRedl->CanCombine( *pNewRedl ) &&
+ n+1 < pRedlineTbl->Count() &&
+ *(*pRedlineTbl)[ n+1 ]->Start() < *pEnd )
+ {
+ // dann kann das zusammengefasst werden, sprich
+ // der neue deckt das schon ab.
+ pNewRedl->SetStart( *pRStt, pStt );
+ pRedlineTbl->DeleteAndDestroy( n );
+ bDec = true;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ // wie soll das verhalten sein????
+ // erstmal so einfuegen
+ break;
+ default:
+ break;
+ }
+ }
+
+ if( pNewRedl )
+ {
+ if( ( *pStt == *pEnd ) &&
+ ( pNewRedl->GetContentIdx() == NULL ) )
+ { // Do not insert empty redlines
+ delete pNewRedl;
+ pNewRedl = 0;
+ }
+ else
+ pRedlineTbl->Insert( pNewRedl );
+ }
+
+ if( bCompress )
+ CompressRedlines();
+ }
+ else
+ {
+ if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
+ {
+ RedlineMode_t eOld = eRedlineMode;
+// auf NONE setzen, damit das Delete::Redo die RedlineDaten wieder richtig
+// zusammen fasst! Der ShowMode muss erhalten bleiben!
+ eRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
+ DeleteAndJoin( *pNewRedl );
+ eRedlineMode = eOld;
+ }
+ delete pNewRedl, pNewRedl = 0;
+ }
+ _CHECK_REDLINE( this )
+
+ return ( 0 != pNewRedl ) || !bError;
+}
+
+void SwDoc::CompressRedlines()
+{
+ _CHECK_REDLINE( this )
+
+ void (SwRedline::*pFnc)(sal_uInt16) = 0;
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ pFnc = &SwRedline::Show;
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ pFnc = &SwRedline::Hide;
+ break;
+ }
+
+ // versuche gleiche zusammenzufassen
+ for( sal_uInt16 n = 1; n < pRedlineTbl->Count(); ++n )
+ {
+ SwRedline* pPrev = (*pRedlineTbl)[ n-1 ],
+ * pCur = (*pRedlineTbl)[ n ];
+ const SwPosition* pPrevStt = pPrev->Start(),
+ * pPrevEnd = pPrevStt == pPrev->GetPoint()
+ ? pPrev->GetMark() : pPrev->GetPoint();
+ const SwPosition* pCurStt = pCur->Start(),
+ * pCurEnd = pCurStt == pCur->GetPoint()
+ ? pCur->GetMark() : pCur->GetPoint();
+ if( *pPrevEnd == *pCurStt && pPrev->CanCombine( *pCur ) &&
+ pPrevStt->nNode.GetNode().StartOfSectionNode() ==
+ pCurEnd->nNode.GetNode().StartOfSectionNode() &&
+ !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() )
+ {
+ // dann koennen die zusammen gefasst werden
+ pPrev->Show();
+ pCur->Show();
+
+ pPrev->SetEnd( *pCur->End() );
+ pRedlineTbl->DeleteAndDestroy( n );
+ --n;
+ if( pFnc )
+ (pPrev->*pFnc)(0);
+ }
+ }
+ _CHECK_REDLINE( this )
+}
+
+bool SwDoc::SplitRedline( const SwPaM& rRange )
+{
+ sal_Bool bChg = sal_False;
+ sal_uInt16 n = 0;
+ const SwPosition* pStt = rRange.Start(),
+ * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
+ : rRange.GetPoint();
+ GetRedline( *pStt, &n );
+ for( ; n < pRedlineTbl->Count() ; ++n )
+ {
+ SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ SwPosition* pTStt = pTmp->Start(),
+ * pTEnd = pTStt == pTmp->GetPoint() ? pTmp->GetMark()
+ : pTmp->GetPoint();
+ if( *pTStt <= *pStt && *pStt <= *pTEnd &&
+ *pTStt <= *pEnd && *pEnd <= *pTEnd )
+ {
+ bChg = sal_True;
+ int nn = 0;
+ if( *pStt == *pTStt )
+ nn += 1;
+ if( *pEnd == *pTEnd )
+ nn += 2;
+
+ SwRedline* pNew = 0;
+ switch( nn )
+ {
+ case 0:
+ pNew = new SwRedline( *pTmp );
+ pTmp->SetEnd( *pStt, pTEnd );
+ pNew->SetStart( *pEnd );
+ break;
+
+ case 1:
+ *pTStt = *pEnd;
+ break;
+
+ case 2:
+ *pTEnd = *pStt;
+ break;
+
+ case 3:
+ pTmp->InvalidateRange();
+ pRedlineTbl->DeleteAndDestroy( n-- );
+ pTmp = 0;
+ break;
+ }
+ if( pTmp && !pTmp->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pTmp, n );
+ }
+ if( pNew )
+ pRedlineTbl->Insert( pNew, n );
+ }
+ else if( *pEnd < *pTStt )
+ break;
+ }
+ return bChg;
+}
+
+bool SwDoc::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
+ sal_uInt16 nDelType )
+{
+ if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & eRedlineMode ||
+ !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
+ return sal_False;
+
+ sal_Bool bChg = sal_False;
+
+ if (bSaveInUndo && GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange );
+ if( pUndo->GetRedlSaveCount() )
+ {
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+ else
+ delete pUndo;
+ }
+
+ const SwPosition* pStt = rRange.Start(),
+ * pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
+ : rRange.GetPoint();
+ sal_uInt16 n = 0;
+ GetRedline( *pStt, &n );
+ for( ; n < pRedlineTbl->Count() ; ++n )
+ {
+ SwRedline* pRedl = (*pRedlineTbl)[ n ];
+ if( USHRT_MAX != nDelType && nDelType != pRedl->GetType() )
+ continue;
+
+ SwPosition* pRStt = pRedl->Start(),
+ * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ sal_Bool bDel = sal_False;
+ switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
+ {
+ case POS_EQUAL:
+ case POS_OUTSIDE:
+ bDel = sal_True;
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( *pEnd == *pREnd )
+ bDel = sal_True;
+ else
+ {
+ pRedl->InvalidateRange();
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ if( *pStt == *pRStt )
+ bDel = sal_True;
+ else
+ {
+ pRedl->InvalidateRange();
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ }
+ break;
+
+ case POS_INSIDE:
+ {
+ // der muss gesplittet werden
+ pRedl->InvalidateRange();
+ if( *pRStt == *pStt )
+ {
+ pRedl->SetStart( *pEnd, pRStt );
+ // neu einsortieren
+ pRedlineTbl->Remove( n );
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ else
+ {
+ SwRedline* pCpy;
+ if( *pREnd != *pEnd )
+ {
+ pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEnd );
+ }
+ else
+ pCpy = 0;
+ pRedl->SetEnd( *pStt, pREnd );
+ if( !pRedl->HasValidRange() )
+ {
+ // neu einsortieren
+ pRedlineTbl->Remove( pRedlineTbl->GetPos( pRedl ));
+ pRedlineTbl->Insert( pRedl );
+ --n;
+ }
+ if( pCpy )
+ pRedlineTbl->Insert( pCpy );
+ }
+ }
+ break;
+
+ case POS_COLLIDE_END:
+ case POS_BEFORE:
+ n = pRedlineTbl->Count();
+ break;
+ default:
+ break;
+ }
+
+ if( bDel )
+ {
+ pRedl->InvalidateRange();
+ pRedlineTbl->DeleteAndDestroy( n-- );
+ bChg = sal_True;
+ }
+ }
+
+ if( bChg )
+ SetModified();
+
+ return bChg;
+}
+
+bool SwDoc::DeleteRedline( const SwStartNode& rNode, bool bSaveInUndo,
+ sal_uInt16 nDelType )
+{
+ SwPaM aTemp(*rNode.EndOfSectionNode(), rNode);
+ return DeleteRedline(aTemp, bSaveInUndo, nDelType);
+}
+
+sal_uInt16 SwDoc::GetRedlinePos( const SwNode& rNd, sal_uInt16 nType ) const
+{
+ const sal_uLong nNdIdx = rNd.GetIndex();
+ for( sal_uInt16 n = 0; n < pRedlineTbl->Count() ; ++n )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ sal_uLong nPt = pTmp->GetPoint()->nNode.GetIndex(),
+ nMk = pTmp->GetMark()->nNode.GetIndex();
+ if( nPt < nMk ) { long nTmp = nMk; nMk = nPt; nPt = nTmp; }
+
+ if( ( USHRT_MAX == nType || nType == pTmp->GetType()) &&
+ nMk <= nNdIdx && nNdIdx <= nPt )
+ return n;
+
+ if( nMk > nNdIdx )
+ break;
+ }
+ return USHRT_MAX;
+}
+
+const SwRedline* SwDoc::GetRedline( const SwPosition& rPos,
+ sal_uInt16* pFndPos ) const
+{
+ sal_uInt16 nO = pRedlineTbl->Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ const SwRedline* pRedl = (*pRedlineTbl)[ nM ];
+ const SwPosition* pStt = pRedl->Start();
+ const SwPosition* pEnd = pStt == pRedl->GetPoint()
+ ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ if( pEnd == pStt
+ ? *pStt == rPos
+ : ( *pStt <= rPos && rPos < *pEnd ) )
+ {
+ /* #107318# returned wrong redline ???*/
+ while( nM && rPos == *(*pRedlineTbl)[ nM - 1 ]->End() &&
+ rPos == *(*pRedlineTbl)[ nM - 1 ]->Start() )
+ {
+ --nM;
+ pRedl = (*pRedlineTbl)[ nM ];
+ }
+
+ if( pFndPos )
+ *pFndPos = nM;
+ return pRedl;
+ }
+ else if( *pEnd <= rPos )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pFndPos )
+ *pFndPos = nU;
+ return 0;
+}
+
+typedef sal_Bool (*Fn_AcceptReject)( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng,
+ const SwPosition* pEndRng);
+
+sal_Bool lcl_AcceptRedline( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng = 0,
+ const SwPosition* pEndRng = 0 )
+{
+ sal_Bool bRet = sal_True;
+ SwRedline* pRedl = rArr[ rPos ];
+ SwPosition *pRStt = 0, *pREnd = 0;
+ SwComparePosition eCmp = POS_OUTSIDE;
+ if( pSttRng && pEndRng )
+ {
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
+ }
+
+ pRedl->InvalidateRange();
+
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ case nsRedlineType_t::REDLINE_FORMAT:
+ {
+ sal_Bool bCheck = sal_False, bReplace = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( *pSttRng == *pRStt )
+ pRedl->SetStart( *pEndRng, pRStt );
+ else
+ {
+ if( *pEndRng != *pREnd )
+ {
+ // aufsplitten
+ SwRedline* pNew = new SwRedline( *pRedl );
+ pNew->SetStart( *pEndRng );
+ rArr.Insert( pNew ); ++rPos;
+ }
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+
+ if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
+ {
+ // neu einsortieren
+ rArr.Remove( rArr.GetPos( pRedl ));
+ rArr.Insert( pRedl );
+ }
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ {
+ SwDoc& rDoc = *pRedl->GetDoc();
+ const SwPosition *pDelStt = 0, *pDelEnd = 0;
+ sal_Bool bDelRedl = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ pDelStt = pSttRng;
+ pDelEnd = pEndRng;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( bCallDelete )
+ {
+ pDelStt = pRStt;
+ pDelEnd = pEndRng;
+ }
+ break;
+ case POS_OVERLAP_BEHIND:
+ if( bCallDelete )
+ {
+ pDelStt = pREnd;
+ pDelEnd = pSttRng;
+ }
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ rArr.Remove( rPos-- );
+ bDelRedl = sal_True;
+ if( bCallDelete )
+ {
+ pDelStt = pRedl->Start();
+ pDelEnd = pRedl->End();
+ }
+ }
+ break;
+ default:
+ bRet = sal_False;
+ }
+
+ if( pDelStt && pDelEnd )
+ {
+ SwPaM aPam( *pDelStt, *pDelEnd );
+ SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
+
+ if( bDelRedl )
+ delete pRedl;
+
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ if( pCSttNd && pCEndNd )
+ rDoc.DeleteAndJoin( aPam );
+ else
+ {
+ rDoc.DeleteRange( aPam );
+
+ if( pCSttNd && !pCEndNd )
+ {
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ rDoc.DelFullPara( aPam );
+ }
+ }
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else if( bDelRedl )
+ delete pRedl;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+sal_Bool lcl_RejectRedline( SwRedlineTbl& rArr, sal_uInt16& rPos,
+ sal_Bool bCallDelete,
+ const SwPosition* pSttRng = 0,
+ const SwPosition* pEndRng = 0 )
+{
+ sal_Bool bRet = sal_True;
+ SwRedline* pRedl = rArr[ rPos ];
+ SwPosition *pRStt = 0, *pREnd = 0;
+ SwComparePosition eCmp = POS_OUTSIDE;
+ if( pSttRng && pEndRng )
+ {
+ pRStt = pRedl->Start();
+ pREnd = pRedl->End();
+ eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
+ }
+
+ pRedl->InvalidateRange();
+
+ switch( pRedl->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ {
+ SwDoc& rDoc = *pRedl->GetDoc();
+ const SwPosition *pDelStt = 0, *pDelEnd = 0;
+ sal_Bool bDelRedl = sal_False;
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ if( bCallDelete )
+ {
+ pDelStt = pSttRng;
+ pDelEnd = pEndRng;
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( bCallDelete )
+ {
+ pDelStt = pRStt;
+ pDelEnd = pEndRng;
+ }
+ break;
+ case POS_OVERLAP_BEHIND:
+ if( bCallDelete )
+ {
+ pDelStt = pREnd;
+ pDelEnd = pSttRng;
+ }
+ break;
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ {
+ // dann den Bereich wieder loeschen
+ rArr.Remove( rPos-- );
+ bDelRedl = sal_True;
+ if( bCallDelete )
+ {
+ pDelStt = pRedl->Start();
+ pDelEnd = pRedl->End();
+ }
+ }
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ if( pDelStt && pDelEnd )
+ {
+ SwPaM aPam( *pDelStt, *pDelEnd );
+
+ SwCntntNode* pCSttNd = pDelStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pDelEnd->nNode.GetNode().GetCntntNode();
+
+ if( bDelRedl )
+ delete pRedl;
+
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern( (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ if( pCSttNd && pCEndNd )
+ rDoc.DeleteAndJoin( aPam );
+ else
+ {
+ rDoc.DeleteRange( aPam );
+
+ if( pCSttNd && !pCEndNd )
+ {
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ rDoc.DelFullPara( aPam );
+ }
+ }
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else if( bDelRedl )
+ delete pRedl;
+ }
+ break;
+ case nsRedlineType_t::REDLINE_DELETE:
+ {
+ SwRedline* pNew = 0;
+ sal_Bool bCheck = sal_False, bReplace = sal_False;
+
+ switch( eCmp )
+ {
+ case POS_INSIDE:
+ {
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ if( *pSttRng == *pRStt )
+ {
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ }
+ else
+ {
+ if( *pEndRng != *pREnd )
+ {
+ // aufsplitten
+ SwRedline* pCpy = new SwRedline( *pRedl );
+ pCpy->SetStart( *pEndRng );
+ rArr.Insert( pCpy ); ++rPos;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ }
+
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ if( pNew )
+ pNew->SetStart( *pSttRng );
+ }
+ }
+ break;
+
+ case POS_OVERLAP_BEFORE:
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ pRedl->SetStart( *pEndRng, pRStt );
+ bReplace = sal_True;
+ if( pNew )
+ pNew->SetEnd( *pEndRng );
+ break;
+
+ case POS_OVERLAP_BEHIND:
+ if( 1 < pRedl->GetStackCount() )
+ {
+ pNew = new SwRedline( *pRedl );
+ pNew->PopData();
+ }
+ pRedl->SetEnd( *pSttRng, pREnd );
+ bCheck = sal_True;
+ if( pNew )
+ pNew->SetStart( *pSttRng );
+ break;
+
+ case POS_OUTSIDE:
+ case POS_EQUAL:
+ if( !pRedl->PopData() )
+ // das RedlineObject loeschen reicht
+ rArr.DeleteAndDestroy( rPos-- );
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+
+ if( pNew )
+ {
+ rArr.Insert( pNew ); ++rPos;
+ }
+
+ if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
+ {
+ // neu einsortieren
+ rArr.Remove( rArr.GetPos( pRedl ));
+ rArr.Insert( pRedl );
+ }
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ case nsRedlineType_t::REDLINE_FMTCOLL:
+ {
+ if( pRedl->GetExtraData() )
+ pRedl->GetExtraData()->Reject( *pRedl );
+ rArr.DeleteAndDestroy( rPos-- );
+ }
+ break;
+
+ default:
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+
+const SwRedline* lcl_FindCurrRedline( const SwPosition& rSttPos,
+ sal_uInt16& rPos,
+ sal_Bool bNext = sal_True )
+{
+ const SwRedline* pFnd = 0;
+ const SwRedlineTbl& rArr = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl();
+ for( ; rPos < rArr.Count() ; ++rPos )
+ {
+ const SwRedline* pTmp = rArr[ rPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition* pRStt = pTmp->Start(),
+ * pREnd = pRStt == pTmp->GetPoint() ? pTmp->GetMark()
+ : pTmp->GetPoint();
+ if( bNext ? *pRStt <= rSttPos : *pRStt < rSttPos )
+ {
+ if( bNext ? *pREnd > rSttPos : *pREnd >= rSttPos )
+ {
+ pFnd = pTmp;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+ return pFnd;
+}
+
+// #111827#
+int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject,
+ SwRedlineTbl& rArr, sal_Bool bCallDelete,
+ const SwPaM& rPam)
+{
+ sal_uInt16 n = 0;
+ int nCount = 0; // #111827#
+
+ const SwPosition* pStt = rPam.Start(),
+ * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
+ : rPam.GetPoint();
+ const SwRedline* pFnd = lcl_FindCurrRedline( *pStt, n, sal_True );
+ if( pFnd && // neu ein Teil davon?
+ ( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd ))
+ {
+ // dann nur die TeilSelektion aufheben
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
+ nCount++; // #111827#
+ ++n;
+ }
+
+ for( ; n < rArr.Count(); ++n )
+ {
+ SwRedline* pTmp = rArr[ n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if( *pTmp->End() <= *pEnd )
+ {
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, 0, 0 ))
+ nCount++; // #111827#
+ }
+ else
+ {
+ if( *pTmp->Start() < *pEnd )
+ {
+ // dann nur in der TeilSelektion aufheben
+ if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
+ nCount++; // #111827#
+ }
+ break;
+ }
+ }
+ }
+ return nCount; // #111827#
+}
+
+void lcl_AdjustRedlineRange( SwPaM& rPam )
+{
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPosition* pStt = rPam.Start(),
+ * pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
+ : rPam.GetPoint();
+ SwDoc* pDoc = rPam.GetDoc();
+ if( !pStt->nContent.GetIndex() &&
+ !pDoc->GetNodes()[ pStt->nNode.GetIndex() - 1 ]->IsCntntNode() )
+ {
+ const SwRedline* pRedl = pDoc->GetRedline( *pStt, 0 );
+ if( pRedl )
+ {
+ const SwPosition* pRStt = pRedl->Start();
+ if( !pRStt->nContent.GetIndex() && pRStt->nNode.GetIndex() ==
+ pStt->nNode.GetIndex() - 1 )
+ *pStt = *pRStt;
+ }
+ }
+ if( pEnd->nNode.GetNode().IsCntntNode() &&
+ !pDoc->GetNodes()[ pEnd->nNode.GetIndex() + 1 ]->IsCntntNode() &&
+ pEnd->nContent.GetIndex() == pEnd->nNode.GetNode().GetCntntNode()->Len() )
+ {
+ const SwRedline* pRedl = pDoc->GetRedline( *pEnd, 0 );
+ if( pRedl )
+ {
+ const SwPosition* pREnd = pRedl->End();
+ if( !pREnd->nContent.GetIndex() && pREnd->nNode.GetIndex() ==
+ pEnd->nNode.GetIndex() + 1 )
+ *pEnd = *pREnd;
+ }
+ }
+}
+
+
+bool SwDoc::AcceptRedline( sal_uInt16 nPos, bool bCallDelete )
+{
+ sal_Bool bRet = sal_False;
+
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ SwRedline* pTmp = (*pRedlineTbl)[ nPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #111827#
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr());
+ GetIDocumentUndoRedo().StartUndo(UNDO_ACCEPT_REDLINE, &aRewriter);
+ }
+
+ int nLoopCnt = 2;
+ sal_uInt16 nSeqNo = pTmp->GetSeqNo();
+
+ do {
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoAcceptRedline(*pTmp) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ bRet |= lcl_AcceptRedline( *pRedlineTbl, nPos, bCallDelete );
+
+ if( nSeqNo )
+ {
+ if( USHRT_MAX == nPos )
+ nPos = 0;
+ sal_uInt16 nFndPos = 2 == nLoopCnt
+ ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
+ : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
+ if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
+ USHRT_MAX != ( nFndPos =
+ pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
+ pTmp = (*pRedlineTbl)[ nPos = nFndPos ];
+ else
+ nLoopCnt = 0;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+
+ if( bRet )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
+ }
+ }
+ return bRet;
+}
+
+bool SwDoc::AcceptRedline( const SwPaM& rPam, bool bCallDelete )
+{
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
+ lcl_AdjustRedlineRange( aPam );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_ACCEPT_REDLINE, NULL );
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoAcceptRedline( aPam ));
+ }
+
+ // #111827#
+ int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *pRedlineTbl,
+ bCallDelete, aPam );
+ if( nRet > 0 )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #111827#
+ String aTmpStr;
+
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet));
+ aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_ACCEPT_REDLINE, &aRewriter );
+ }
+ return nRet != 0;
+}
+
+bool SwDoc::RejectRedline( sal_uInt16 nPos, bool bCallDelete )
+{
+ sal_Bool bRet = sal_False;
+
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ SwRedline* pTmp = (*pRedlineTbl)[ nPos ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #111827#
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, pTmp->GetDescr());
+ GetIDocumentUndoRedo().StartUndo(UNDO_REJECT_REDLINE, &aRewriter);
+ }
+
+ int nLoopCnt = 2;
+ sal_uInt16 nSeqNo = pTmp->GetSeqNo();
+
+ do {
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ SwUndo *const pUndo( new SwUndoRejectRedline( *pTmp ) );
+ GetIDocumentUndoRedo().AppendUndo(pUndo);
+ }
+
+ bRet |= lcl_RejectRedline( *pRedlineTbl, nPos, bCallDelete );
+
+ if( nSeqNo )
+ {
+ if( USHRT_MAX == nPos )
+ nPos = 0;
+ sal_uInt16 nFndPos = 2 == nLoopCnt
+ ? pRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
+ : pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
+ if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
+ USHRT_MAX != ( nFndPos =
+ pRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
+ pTmp = (*pRedlineTbl)[ nPos = nFndPos ];
+ else
+ nLoopCnt = 0;
+ }
+ else
+ nLoopCnt = 0;
+
+ } while( nLoopCnt );
+
+ if( bRet )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
+ }
+ }
+ return bRet;
+}
+
+bool SwDoc::RejectRedline( const SwPaM& rPam, bool bCallDelete )
+{
+ // aufjedenfall auf sichtbar umschalten
+ if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
+ (nsRedlineMode_t::REDLINE_SHOW_MASK & eRedlineMode) )
+ SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | eRedlineMode));
+
+ // die Selektion steht nur im ContentBereich. Wenn es aber Redlines
+ // davor oder dahinter auf nicht ContentNodes stehen, dann erweiter die
+ // die Selection auf diese
+ SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
+ lcl_AdjustRedlineRange( aPam );
+
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ GetIDocumentUndoRedo().StartUndo( UNDO_REJECT_REDLINE, NULL );
+ GetIDocumentUndoRedo().AppendUndo( new SwUndoRejectRedline(aPam) );
+ }
+
+ // #111827#
+ int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *pRedlineTbl,
+ bCallDelete, aPam );
+ if( nRet > 0 )
+ {
+ CompressRedlines();
+ SetModified();
+ }
+ if (GetIDocumentUndoRedo().DoesUndo())
+ {
+ // #111827#
+ String aTmpStr;
+
+ {
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, String::CreateFromInt32(nRet));
+ aTmpStr = aRewriter.Apply(String(SW_RES(STR_N_REDLINES)));
+ }
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ GetIDocumentUndoRedo().EndUndo( UNDO_REJECT_REDLINE, &aRewriter );
+ }
+
+ return nRet != 0;
+}
+
+const SwRedline* SwDoc::SelNextRedline( SwPaM& rPam ) const
+{
+ rPam.DeleteMark();
+ rPam.SetMark();
+
+ SwPosition& rSttPos = *rPam.GetPoint();
+ SwPosition aSavePos( rSttPos );
+ sal_Bool bRestart;
+
+ // sollte die StartPos auf dem letzen gueligen ContentNode stehen,
+ // dann aufjedenfall das naechste Redline nehmen
+ sal_uInt16 n = 0;
+ const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_True );
+ if( pFnd )
+ {
+ const SwPosition* pEnd = pFnd->End();
+ if( !pEnd->nNode.GetNode().IsCntntNode() )
+ {
+ SwNodeIndex aTmp( pEnd->nNode );
+ SwCntntNode* pCNd = GetNodes().GoPrevSection( &aTmp );
+ if( !pCNd || ( aTmp == rSttPos.nNode &&
+ pCNd->Len() == rSttPos.nContent.GetIndex() ))
+ pFnd = 0;
+ }
+ if( pFnd )
+ rSttPos = *pFnd->End();
+ }
+
+ do {
+ bRestart = sal_False;
+
+ for( ; !pFnd && n < pRedlineTbl->Count(); ++n )
+ {
+ pFnd = (*pRedlineTbl)[ n ];
+ if( pFnd->HasMark() && pFnd->IsVisible() )
+ {
+ *rPam.GetMark() = *pFnd->Start();
+ rSttPos = *pFnd->End();
+ break;
+ }
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ // alle vom gleichen Typ und Author, die hinter einander liegen
+ // zu einer Selektion zusammenfassen.
+ const SwPosition* pPrevEnd = pFnd->End();
+ while( ++n < pRedlineTbl->Count() )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition *pRStt;
+ if( pFnd->GetType() == pTmp->GetType() &&
+ pFnd->GetAuthor() == pTmp->GetAuthor() &&
+ ( *pPrevEnd == *( pRStt = pTmp->Start() ) ||
+ IsPrevPos( *pPrevEnd, *pRStt )) )
+ {
+ pPrevEnd = pTmp->End();
+ rSttPos = *pPrevEnd;
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ const SwRedline* pSaveFnd = pFnd;
+
+ SwCntntNode* pCNd;
+ SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) )
+ {
+ if( *pIdx <= rPam.GetPoint()->nNode )
+ rPam.GetMark()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ pIdx = &rPam.GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) )
+ {
+ if( *pIdx >= rPam.GetMark()->nNode )
+ rPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = 0;
+ }
+ }
+
+ if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
+ {
+ if( n < pRedlineTbl->Count() )
+ {
+ bRestart = sal_True;
+ *rPam.GetPoint() = *pSaveFnd->End();
+ }
+ else
+ {
+ rPam.DeleteMark();
+ *rPam.GetPoint() = aSavePos;
+ }
+ pFnd = 0;
+ }
+ }
+ } while( bRestart );
+
+ return pFnd;
+}
+
+const SwRedline* SwDoc::SelPrevRedline( SwPaM& rPam ) const
+{
+ rPam.DeleteMark();
+ rPam.SetMark();
+
+ SwPosition& rSttPos = *rPam.GetPoint();
+ SwPosition aSavePos( rSttPos );
+ sal_Bool bRestart;
+
+ // sollte die StartPos auf dem ersten gueligen ContentNode stehen,
+ // dann aufjedenfall das vorherige Redline nehmen
+ sal_uInt16 n = 0;
+ const SwRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, sal_False );
+ if( pFnd )
+ {
+ const SwPosition* pStt = pFnd->Start();
+ if( !pStt->nNode.GetNode().IsCntntNode() )
+ {
+ SwNodeIndex aTmp( pStt->nNode );
+ SwCntntNode* pCNd = GetNodes().GoNextSection( &aTmp );
+ if( !pCNd || ( aTmp == rSttPos.nNode &&
+ !rSttPos.nContent.GetIndex() ))
+ pFnd = 0;
+ }
+ if( pFnd )
+ rSttPos = *pFnd->Start();
+ }
+
+ do {
+ bRestart = sal_False;
+
+ while( !pFnd && 0 < n )
+ {
+ pFnd = (*pRedlineTbl)[ --n ];
+ if( pFnd->HasMark() && pFnd->IsVisible() )
+ {
+ *rPam.GetMark() = *pFnd->End();
+ rSttPos = *pFnd->Start();
+ }
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ // alle vom gleichen Typ und Author, die hinter einander liegen
+ // zu einer Selektion zusammenfassen.
+ const SwPosition* pNextStt = pFnd->Start();
+ while( 0 < n )
+ {
+ const SwRedline* pTmp = (*pRedlineTbl)[ --n ];
+ if( pTmp->HasMark() && pTmp->IsVisible() )
+ {
+ const SwPosition *pREnd;
+ if( pFnd->GetType() == pTmp->GetType() &&
+ pFnd->GetAuthor() == pTmp->GetAuthor() &&
+ ( *pNextStt == *( pREnd = pTmp->End() ) ||
+ IsPrevPos( *pREnd, *pNextStt )) )
+ {
+ pNextStt = pTmp->Start();
+ rSttPos = *pNextStt;
+ }
+ else
+ {
+ ++n;
+ break;
+ }
+ }
+ }
+ }
+
+ if( pFnd )
+ {
+ const SwRedline* pSaveFnd = pFnd;
+
+ SwCntntNode* pCNd;
+ SwNodeIndex* pIdx = &rPam.GetMark()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoPrevSection( pIdx )) )
+ {
+ if( *pIdx >= rPam.GetPoint()->nNode )
+ rPam.GetMark()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ pFnd = 0;
+ }
+
+ if( pFnd )
+ {
+ pIdx = &rPam.GetPoint()->nNode;
+ if( !pIdx->GetNode().IsCntntNode() &&
+ 0 != ( pCNd = GetNodes().GoNextSection( pIdx )) )
+ {
+ if( *pIdx <= rPam.GetMark()->nNode )
+ rPam.GetPoint()->nContent.Assign( pCNd, 0 );
+ else
+ pFnd = 0;
+ }
+ }
+
+ if( !pFnd || *rPam.GetMark() == *rPam.GetPoint() )
+ {
+ if( n )
+ {
+ bRestart = sal_True;
+ *rPam.GetPoint() = *pSaveFnd->Start();
+ }
+ else
+ {
+ rPam.DeleteMark();
+ *rPam.GetPoint() = aSavePos;
+ }
+ pFnd = 0;
+ }
+ }
+ } while( bRestart );
+
+ return pFnd;
+}
+
+// Kommentar am Redline setzen
+bool SwDoc::SetRedlineComment( const SwPaM& rPaM, const String& rS )
+{
+ sal_Bool bRet = sal_False;
+ const SwPosition* pStt = rPaM.Start(),
+ * pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
+ : rPaM.GetPoint();
+ sal_uInt16 n = 0;
+ if( lcl_FindCurrRedline( *pStt, n, sal_True ) )
+ {
+ for( ; n < pRedlineTbl->Count(); ++n )
+ {
+ bRet = sal_True;
+ SwRedline* pTmp = (*pRedlineTbl)[ n ];
+ if( pStt != pEnd && *pTmp->Start() > *pEnd )
+ break;
+
+ pTmp->SetComment( rS );
+ if( *pTmp->End() >= *pEnd )
+ break;
+ }
+ }
+ if( bRet )
+ SetModified();
+
+ return bRet;
+}
+
+// legt gebenenfalls einen neuen Author an
+sal_uInt16 SwDoc::GetRedlineAuthor()
+{
+ return SW_MOD()->GetRedlineAuthor();
+}
+
+ // fuer die Reader usw. - neuen Author in die Tabelle eintragen
+sal_uInt16 SwDoc::InsertRedlineAuthor( const String& rNew )
+{
+ return SW_MOD()->InsertRedlineAuthor(rNew);
+}
+
+void SwDoc::UpdateRedlineAttr()
+{
+ const SwRedlineTbl& rTbl = GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->IsVisible() )
+ pRedl->InvalidateRange();
+ }
+}
+
+ // setze Kommentar-Text fuers Redline, das dann per AppendRedline
+ // hereinkommt. Wird vom Autoformat benutzt. 0-Pointer setzt den Modus
+ // wieder zurueck. Pointer wird nicht kopiert, muss also gueltig bleiben!
+void SwDoc::SetAutoFmtRedlineComment( const String* pTxt, sal_uInt16 nSeqNo )
+{
+ mbIsAutoFmtRedline = 0 != pTxt;
+ if( pTxt )
+ {
+ if( !pAutoFmtRedlnComment )
+ pAutoFmtRedlnComment = new String( *pTxt );
+ else
+ *pAutoFmtRedlnComment = *pTxt;
+ }
+ else if( pAutoFmtRedlnComment )
+ delete pAutoFmtRedlnComment, pAutoFmtRedlnComment = 0;
+
+ nAutoFmtRedlnCommentNo = nSeqNo;
+}
+
+void SwDoc::SetRedlinePassword(
+ /*[in]*/const uno::Sequence <sal_Int8>& rNewPassword)
+{
+ aRedlinePasswd = rNewPassword;
+ SetModified();
+}
+
+/* */
+
+sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_Bool bIns )
+{
+ sal_Bool bRet = sal_False;
+ if( p->HasValidRange() )
+ {
+ bRet = _SwRedlineTbl::Insert( p );
+ p->CallDisplayFunc();
+ }
+ else if( bIns )
+ bRet = InsertWithValidRanges( p );
+ else
+ {
+ ASSERT( !this, "Redline: falscher Bereich" );
+ }
+ return bRet;
+}
+
+sal_Bool SwRedlineTbl::Insert( SwRedlinePtr& p, sal_uInt16& rP, sal_Bool bIns )
+{
+ sal_Bool bRet = sal_False;
+ if( p->HasValidRange() )
+ {
+ bRet = _SwRedlineTbl::Insert( p, rP );
+ p->CallDisplayFunc();
+ }
+ else if( bIns )
+ bRet = InsertWithValidRanges( p, &rP );
+ else
+ {
+ ASSERT( !this, "Redline: falscher Bereich" );
+ }
+ return bRet;
+}
+
+sal_Bool SwRedlineTbl::InsertWithValidRanges( SwRedlinePtr& p, sal_uInt16* pInsPos )
+{
+ // erzeuge aus den Selektion gueltige "Teilbereiche".
+ sal_Bool bAnyIns = sal_False;
+ SwPosition* pStt = p->Start(),
+ * pEnd = pStt == p->GetPoint() ? p->GetMark() : p->GetPoint();
+ SwPosition aNewStt( *pStt );
+ SwNodes& rNds = aNewStt.nNode.GetNodes();
+ SwCntntNode* pC;
+
+ if( !aNewStt.nNode.GetNode().IsCntntNode() )
+ {
+ pC = rNds.GoNext( &aNewStt.nNode );
+ if( pC )
+ aNewStt.nContent.Assign( pC, 0 );
+ else
+ aNewStt.nNode = rNds.GetEndOfContent();
+ }
+
+ SwRedline* pNew = 0;
+ sal_uInt16 nInsPos;
+
+ if( aNewStt < *pEnd )
+ do {
+ if( !pNew )
+ pNew = new SwRedline( p->GetRedlineData(), aNewStt );
+ else
+ {
+ pNew->DeleteMark();
+ *pNew->GetPoint() = aNewStt;
+ }
+
+ pNew->SetMark();
+ GoEndSection( pNew->GetPoint() );
+ // i60396: If the redlines starts before a table but the table is the last member
+ // of the section, the GoEndSection will end inside the table.
+ // This will result in an incorrect redline, so we've to go back
+ SwNode* pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode();
+ // We end in a table when pTab != 0
+ if( pTab && !pNew->GetMark()->nNode.GetNode().StartOfSectionNode()->FindTableNode() )
+ { // but our Mark was outside the table => Correction
+ do
+ {
+ // We want to be before the table
+ *pNew->GetPoint() = SwPosition(*pTab);
+ pC = GoPreviousNds( &pNew->GetPoint()->nNode, sal_False ); // here we are.
+ if( pC )
+ pNew->GetPoint()->nContent.Assign( pC, 0 );
+ pTab = pNew->GetPoint()->nNode.GetNode().StartOfSectionNode()->FindTableNode();
+ }while( pTab ); // If there is another table we have to repeat our step backwards
+ }
+
+ if( *pNew->GetPoint() > *pEnd )
+ {
+ pC = 0;
+ if( aNewStt.nNode != pEnd->nNode )
+ do {
+ SwNode& rCurNd = aNewStt.nNode.GetNode();
+ if( rCurNd.IsStartNode() )
+ {
+ if( rCurNd.EndOfSectionIndex() < pEnd->nNode.GetIndex() )
+ aNewStt.nNode = *rCurNd.EndOfSectionNode();
+ else
+ break;
+ }
+ else if( rCurNd.IsCntntNode() )
+ pC = rCurNd.GetCntntNode();
+ aNewStt.nNode++;
+ } while( aNewStt.nNode.GetIndex() < pEnd->nNode.GetIndex() );
+
+ if( aNewStt.nNode == pEnd->nNode )
+ aNewStt.nContent = pEnd->nContent;
+ else if( pC )
+ {
+ aNewStt.nNode = *pC;
+ aNewStt.nContent.Assign( pC, pC->Len() );
+ }
+
+ if( aNewStt <= *pEnd )
+ *pNew->GetPoint() = aNewStt;
+ }
+ else
+ aNewStt = *pNew->GetPoint();
+#ifdef DEBUG
+ CheckPosition( pNew->GetPoint(), pNew->GetMark() );
+#endif
+ if( *pNew->GetPoint() != *pNew->GetMark() &&
+ _SwRedlineTbl::Insert( pNew, nInsPos ) )
+ {
+ pNew->CallDisplayFunc();
+ bAnyIns = sal_True;
+ pNew = 0;
+ if( pInsPos && *pInsPos < nInsPos )
+ *pInsPos = nInsPos;
+ }
+
+ if( aNewStt >= *pEnd ||
+ 0 == (pC = rNds.GoNext( &aNewStt.nNode )) )
+ break;
+
+ aNewStt.nContent.Assign( pC, 0 );
+
+ } while( aNewStt < *pEnd );
+
+ delete pNew;
+ delete p, p = 0;
+ return bAnyIns;
+}
+
+void SwRedlineTbl::Remove( sal_uInt16 nP, sal_uInt16 nL )
+{
+ SwDoc* pDoc = 0;
+ if( !nP && nL && nL == _SwRedlineTbl::Count() )
+ pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc();
+
+ _SwRedlineTbl::Remove( nP, nL );
+
+ ViewShell* pSh;
+ if( pDoc && !pDoc->IsInDtor() &&
+ 0 != ( pSh = pDoc->GetCurrentViewShell()) ) //swmod 071108//swmod 071225
+ pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
+}
+
+void SwRedlineTbl::DeleteAndDestroy( sal_uInt16 nP, sal_uInt16 nL )
+{
+ SwDoc* pDoc = 0;
+ if( !nP && nL && nL == _SwRedlineTbl::Count() )
+ pDoc = _SwRedlineTbl::GetObject( 0 )->GetDoc();
+
+ _SwRedlineTbl::DeleteAndDestroy( nP, nL );
+
+ ViewShell* pSh;
+ if( pDoc && !pDoc->IsInDtor() &&
+ 0 != ( pSh = pDoc->GetCurrentViewShell() ) ) //swmod 071108//swmod 071225
+ pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
+}
+
+// suche den naechsten oder vorherigen Redline mit dergleichen Seq.No
+// Mit dem Lookahead kann die Suche eingeschraenkt werden. 0 oder
+// USHRT_MAX suchen im gesamten Array.
+sal_uInt16 SwRedlineTbl::FindNextOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const
+{
+ return nSttPos + 1 < _SwRedlineTbl::Count()
+ ? FindNextSeqNo( _SwRedlineTbl::GetObject( nSttPos )
+ ->GetSeqNo(), nSttPos+1, nLookahead )
+ : USHRT_MAX;
+}
+
+sal_uInt16 SwRedlineTbl::FindPrevOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const
+{
+ return nSttPos ? FindPrevSeqNo( _SwRedlineTbl::GetObject(
+ nSttPos )->GetSeqNo(),
+ nSttPos-1, nLookahead )
+ : USHRT_MAX;
+}
+
+sal_uInt16 SwRedlineTbl::FindNextSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos,
+ sal_uInt16 nLookahead ) const
+{
+ sal_uInt16 nRet = USHRT_MAX, nEnd;
+ if( nSeqNo && nSttPos < _SwRedlineTbl::Count() )
+ {
+ nEnd = _SwRedlineTbl::Count();
+ if( nLookahead && USHRT_MAX != nLookahead &&
+ nSttPos + nLookahead < _SwRedlineTbl::Count() )
+ nEnd = nSttPos + nLookahead;
+
+ for( ; nSttPos < nEnd; ++nSttPos )
+ if( nSeqNo == _SwRedlineTbl::GetObject( nSttPos )->GetSeqNo() )
+ {
+ nRet = nSttPos;
+ break;
+ }
+ }
+ return nRet;
+}
+
+sal_uInt16 SwRedlineTbl::FindPrevSeqNo( sal_uInt16 nSeqNo, sal_uInt16 nSttPos,
+ sal_uInt16 nLookahead ) const
+{
+ sal_uInt16 nRet = USHRT_MAX, nEnd;
+ if( nSeqNo && nSttPos < _SwRedlineTbl::Count() )
+ {
+ nEnd = 0;
+ if( nLookahead && USHRT_MAX != nLookahead && nSttPos > nLookahead )
+ nEnd = nSttPos - nLookahead;
+
+ ++nSttPos;
+ while( nSttPos > nEnd )
+ if( nSeqNo == _SwRedlineTbl::GetObject( --nSttPos )->GetSeqNo() )
+ {
+ nRet = nSttPos;
+ break;
+ }
+ }
+ return nRet;
+}
+
+/* */
+
+SwRedlineExtraData::~SwRedlineExtraData()
+{
+}
+
+void SwRedlineExtraData::Accept( SwPaM& ) const
+{
+}
+
+void SwRedlineExtraData::Reject( SwPaM& ) const
+{
+}
+
+int SwRedlineExtraData::operator == ( const SwRedlineExtraData& ) const
+{
+ return sal_False;
+}
+
+
+SwRedlineExtraData_FmtColl::SwRedlineExtraData_FmtColl( const String& rColl,
+ sal_uInt16 nPoolFmtId,
+ const SfxItemSet* pItemSet )
+ : sFmtNm(rColl), pSet(0), nPoolId(nPoolFmtId)
+{
+ if( pItemSet && pItemSet->Count() )
+ pSet = new SfxItemSet( *pItemSet );
+}
+
+SwRedlineExtraData_FmtColl::~SwRedlineExtraData_FmtColl()
+{
+ delete pSet;
+}
+
+SwRedlineExtraData* SwRedlineExtraData_FmtColl::CreateNew() const
+{
+ return new SwRedlineExtraData_FmtColl( sFmtNm, nPoolId, pSet );
+}
+
+void SwRedlineExtraData_FmtColl::Reject( SwPaM& rPam ) const
+{
+ SwDoc* pDoc = rPam.GetDoc();
+
+// was ist mit Undo ? ist das abgeschaltet ??
+ SwTxtFmtColl* pColl = USHRT_MAX == nPoolId
+ ? pDoc->FindTxtFmtCollByName( sFmtNm )
+ : pDoc->GetTxtCollFromPool( nPoolId );
+ if( pColl )
+ pDoc->SetTxtFmtColl( rPam, pColl, false );
+
+ if( pSet )
+ {
+ rPam.SetMark();
+ SwPosition& rMark = *rPam.GetMark();
+ SwTxtNode* pTNd = rMark.nNode.GetNode().GetTxtNode();
+ if( pTNd )
+ {
+ rMark.nContent.Assign( pTNd, pTNd->GetTxt().Len() );
+
+ if( pTNd->HasSwAttrSet() )
+ {
+ // nur die setzen, die nicht mehr vorhanden sind. Andere
+ // koennen jetzt veraendert drin stehen, aber die werden
+ // nicht angefasst.
+ SfxItemSet aTmp( *pSet );
+ aTmp.Differentiate( *pTNd->GetpSwAttrSet() );
+ pDoc->InsertItemSet( rPam, aTmp, 0 );
+ }
+ else
+ {
+ pDoc->InsertItemSet( rPam, *pSet, 0 );
+ }
+ }
+ rPam.DeleteMark();
+ }
+}
+
+int SwRedlineExtraData_FmtColl::operator == ( const SwRedlineExtraData& r) const
+{
+ const SwRedlineExtraData_FmtColl& rCmp = (SwRedlineExtraData_FmtColl&)r;
+ return sFmtNm == rCmp.sFmtNm && nPoolId == rCmp.nPoolId &&
+ ( ( !pSet && !rCmp.pSet ) ||
+ ( pSet && rCmp.pSet && *pSet == *rCmp.pSet ) );
+}
+
+void SwRedlineExtraData_FmtColl::SetItemSet( const SfxItemSet& rSet )
+{
+ delete pSet;
+ if( rSet.Count() )
+ pSet = new SfxItemSet( rSet );
+ else
+ pSet = 0;
+}
+
+
+SwRedlineExtraData_Format::SwRedlineExtraData_Format( const SfxItemSet& rSet )
+{
+ SfxItemIter aIter( rSet );
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ while( sal_True )
+ {
+ aWhichIds.Insert( pItem->Which(), aWhichIds.Count() );
+ if( aIter.IsAtEnd() )
+ break;
+ pItem = aIter.NextItem();
+ }
+}
+
+SwRedlineExtraData_Format::SwRedlineExtraData_Format(
+ const SwRedlineExtraData_Format& rCpy )
+ : SwRedlineExtraData(), aWhichIds( (sal_uInt8)rCpy.aWhichIds.Count() )
+{
+ aWhichIds.Insert( &rCpy.aWhichIds, 0 );
+}
+
+SwRedlineExtraData_Format::~SwRedlineExtraData_Format()
+{
+}
+
+SwRedlineExtraData* SwRedlineExtraData_Format::CreateNew() const
+{
+ return new SwRedlineExtraData_Format( *this );
+}
+
+void SwRedlineExtraData_Format::Reject( SwPaM& rPam ) const
+{
+ SwDoc* pDoc = rPam.GetDoc();
+
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE)));
+
+ // eigentlich muesste hier das Attribut zurueck gesetzt werden!!!
+ for( sal_uInt16 n = 0, nEnd = aWhichIds.Count(); n < nEnd; ++n )
+ {
+ pDoc->InsertPoolItem( rPam, *GetDfltAttr( aWhichIds[ n ] ),
+ nsSetAttrMode::SETATTR_DONTEXPAND );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+int SwRedlineExtraData_Format::operator == ( const SwRedlineExtraData& rCmp ) const
+{
+ int nRet = 1;
+ sal_uInt16 n = 0, nEnd = aWhichIds.Count();
+ if( nEnd != ((SwRedlineExtraData_Format&)rCmp).aWhichIds.Count() )
+ nRet = 0;
+ else
+ for( ; n < nEnd; ++n )
+ if( ((SwRedlineExtraData_Format&)rCmp).aWhichIds[n] != aWhichIds[n])
+ {
+ nRet = 0;
+ break;
+ }
+ return nRet;
+}
+
+/* */
+
+SwRedlineData::SwRedlineData( RedlineType_t eT, sal_uInt16 nAut )
+ : pNext( 0 ), pExtraData( 0 ), eType( eT ), nAuthor( nAut ), nSeqNo( 0 )
+{
+ aStamp.SetSec( 0 );
+ aStamp.Set100Sec( 0 );
+}
+
+SwRedlineData::SwRedlineData( const SwRedlineData& rCpy, sal_Bool bCpyNext )
+ :
+ pNext( (bCpyNext && rCpy.pNext) ? new SwRedlineData( *rCpy.pNext ) : 0 ),
+ pExtraData( rCpy.pExtraData ? rCpy.pExtraData->CreateNew() : 0 ),
+ sComment( rCpy.sComment ), aStamp( rCpy.aStamp ), eType( rCpy.eType ),
+ nAuthor( rCpy.nAuthor ), nSeqNo( rCpy.nSeqNo )
+{
+}
+
+ // fuer sw3io: pNext geht in eigenen Besitz ueber!
+SwRedlineData::SwRedlineData(RedlineType_t eT, sal_uInt16 nAut, const DateTime& rDT,
+ const String& rCmnt, SwRedlineData *pNxt, SwRedlineExtraData* pData)
+ : pNext(pNxt), pExtraData(pData), sComment(rCmnt), aStamp(rDT),
+ eType(eT), nAuthor(nAut), nSeqNo(0)
+{
+}
+
+SwRedlineData::~SwRedlineData()
+{
+ delete pExtraData;
+ delete pNext;
+}
+
+ // ExtraData wird kopiert, der Pointer geht also NICHT in den Besitz
+ // des RedlineObjectes!
+void SwRedlineData::SetExtraData( const SwRedlineExtraData* pData )
+{
+ delete pExtraData;
+
+ if( pData )
+ pExtraData = pData->CreateNew();
+ else
+ pExtraData = 0;
+}
+
+// #111827#
+String SwRedlineData::GetDescr() const
+{
+ String aResult;
+
+ aResult += String(SW_RES(STR_REDLINE_INSERT + GetType()));
+
+ return aResult;
+}
+
+/* */
+
+SwRedline::SwRedline(RedlineType_t eTyp, const SwPaM& rPam )
+ : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ),
+ pRedlineData( new SwRedlineData( eTyp, GetDoc()->GetRedlineAuthor() ) ),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rPam.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::SwRedline( const SwRedlineData& rData, const SwPaM& rPam )
+ : SwPaM( *rPam.GetMark(), *rPam.GetPoint() ),
+ pRedlineData( new SwRedlineData( rData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rPam.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::SwRedline( const SwRedlineData& rData, const SwPosition& rPos )
+ : SwPaM( rPos ),
+ pRedlineData( new SwRedlineData( rData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+}
+
+SwRedline::SwRedline( const SwRedline& rCpy )
+ : SwPaM( *rCpy.GetMark(), *rCpy.GetPoint() ),
+ pRedlineData( new SwRedlineData( *rCpy.pRedlineData )),
+ pCntntSect( 0 )
+{
+ bDelLastPara = bIsLastParaDelete = sal_False;
+ bIsVisible = sal_True;
+ if( !rCpy.HasMark() )
+ DeleteMark();
+}
+
+SwRedline::~SwRedline()
+{
+ if( pCntntSect )
+ {
+ // dann den Content Bereich loeschen
+ if( !GetDoc()->IsInDtor() )
+ GetDoc()->DeleteSection( &pCntntSect->GetNode() );
+ delete pCntntSect;
+ }
+ delete pRedlineData;
+}
+
+// liegt eine gueltige Selektion vor?
+sal_Bool SwRedline::HasValidRange() const
+{
+ const SwNode* pPtNd = &GetPoint()->nNode.GetNode(),
+ * pMkNd = &GetMark()->nNode.GetNode();
+ if( pPtNd->StartOfSectionNode() == pMkNd->StartOfSectionNode() &&
+ !pPtNd->StartOfSectionNode()->IsTableNode() &&
+ // JP 18.5.2001: Bug 87222 - invalid if points on the end of content
+ // DVO 25.03.2002: #96530# end-of-content only invalid if no content
+ // index exists
+ ( pPtNd != pMkNd || GetContentIdx() != NULL ||
+ pPtNd != &pPtNd->GetNodes().GetEndOfContent() )
+ )
+ return sal_True;
+ return sal_False;
+}
+
+void SwRedline::CallDisplayFunc( sal_uInt16 nLoop )
+{
+ switch( nsRedlineMode_t::REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() )
+ {
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ Show( nLoop );
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_INSERT:
+ Hide( nLoop );
+ break;
+ case nsRedlineMode_t::REDLINE_SHOW_DELETE:
+ ShowOriginal( nLoop );
+ break;
+ }
+}
+
+void SwRedline::Show( sal_uInt16 nLoop )
+{
+ if( 1 <= nLoop )
+ {
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ switch( GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_True;
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_True;
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+ }
+}
+
+void SwRedline::Hide( sal_uInt16 nLoop )
+{
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ switch( GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_True;
+ if( 1 <= nLoop )
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_False;
+ switch( nLoop )
+ {
+ case 0: MoveToSection(); break;
+ case 1: CopyToSection(); break;
+ case 2: DelCopyOfSection(); break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ if( 1 <= nLoop )
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+void SwRedline::ShowOriginal( sal_uInt16 nLoop )
+{
+ SwDoc* pDoc = GetDoc();
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ SwRedlineData* pCur;
+
+ pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ // bestimme den Type, ist der erste auf Stack
+ for( pCur = pRedlineData; pCur->pNext; )
+ pCur = pCur->pNext;
+
+ switch( pCur->eType )
+ {
+ case nsRedlineType_t::REDLINE_INSERT: // Inhalt wurde eingefuegt
+ bIsVisible = sal_False;
+ switch( nLoop )
+ {
+ case 0: MoveToSection(); break;
+ case 1: CopyToSection(); break;
+ case 2: DelCopyOfSection(); break;
+ }
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE: // Inhalt wurde geloescht
+ bIsVisible = sal_True;
+ if( 1 <= nLoop )
+ MoveFromSection();
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT: // Attributierung wurde angewendet
+ case nsRedlineType_t::REDLINE_TABLE: // TabellenStruktur wurde veraendert
+ if( 1 <= nLoop )
+ InvalidateRange();
+ break;
+ default:
+ break;
+ }
+ pDoc->SetRedlineMode_intern( eOld );
+}
+
+
+void SwRedline::InvalidateRange() // das Layout anstossen
+{
+ sal_uLong nSttNd = GetMark()->nNode.GetIndex(),
+ nEndNd = GetPoint()->nNode.GetIndex();
+ sal_uInt16 nSttCnt = GetMark()->nContent.GetIndex(),
+ nEndCnt = GetPoint()->nContent.GetIndex();
+
+ if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
+ {
+ sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
+ nTmp = nSttCnt; nSttCnt = nEndCnt; nEndCnt = (sal_uInt16)nTmp;
+ }
+
+ SwUpdateAttr aHt( 0, 0, RES_FMT_CHG );
+ SwNodes& rNds = GetDoc()->GetNodes();
+ SwNode* pNd;
+ for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
+ if( ND_TEXTNODE == ( pNd = rNds[ n ] )->GetNodeType() )
+ {
+ aHt.nStart = n == nSttNd ? nSttCnt : 0;
+ aHt.nEnd = n == nEndNd ? nEndCnt : ((SwTxtNode*)pNd)->GetTxt().Len();
+ ((SwTxtNode*)pNd)->ModifyNotification( &aHt, &aHt );
+ }
+}
+
+/*************************************************************************
+ * SwRedline::CalcStartEnd()
+ * Calculates the start and end position of the intersection rTmp and
+ * text node nNdIdx
+ *************************************************************************/
+
+void SwRedline::CalcStartEnd( sal_uLong nNdIdx, sal_uInt16& nStart, sal_uInt16& nEnd ) const
+{
+ const SwPosition *pRStt = Start(), *pREnd = End();
+ if( pRStt->nNode < nNdIdx )
+ {
+ if( pREnd->nNode > nNdIdx )
+ {
+ nStart = 0; // Absatz ist komplett enthalten
+ nEnd = STRING_LEN;
+ }
+ else
+ {
+ ASSERT( pREnd->nNode == nNdIdx,
+ "SwRedlineItr::Seek: GetRedlinePos Error" );
+ nStart = 0; // Absatz wird vorne ueberlappt
+ nEnd = pREnd->nContent.GetIndex();
+ }
+ }
+ else if( pRStt->nNode == nNdIdx )
+ {
+ nStart = pRStt->nContent.GetIndex();
+ if( pREnd->nNode == nNdIdx )
+ nEnd = pREnd->nContent.GetIndex(); // Innerhalb des Absatzes
+ else
+ nEnd = STRING_LEN; // Absatz wird hinten ueberlappt
+ }
+ else
+ {
+ nStart = STRING_LEN;
+ nEnd = STRING_LEN;
+ }
+}
+
+void SwRedline::MoveToSection()
+{
+ if( !pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwDoc* pDoc = GetDoc();
+ SwPaM aPam( *pStt, *pEnd );
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ if( !pCSttNd )
+ {
+ // damit die Indizies der anderen Redlines nicht mitverschoben
+ // werden, diese aufs Ende setzen (ist exclusive).
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->GetBound(sal_True) == *pStt )
+ pRedl->GetBound(sal_True) = *pEnd;
+ if( pRedl->GetBound(sal_False) == *pStt )
+ pRedl->GetBound(sal_False) = *pEnd;
+ }
+ }
+
+ SwStartNode* pSttNd;
+ SwNodes& rNds = pDoc->GetNodes();
+ if( pCSttNd || pCEndNd )
+ {
+ SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
+ : (pCEndNd && pCEndNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCEndNd)->GetTxtColl()
+ : pDoc->GetTxtCollFromPool(
+ RES_POOLCOLL_STANDARD );
+
+ pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode, pColl );
+ SwTxtNode* pTxtNd = rNds[ pSttNd->GetIndex() + 1 ]->GetTxtNode();
+
+ SwNodeIndex aNdIdx( *pTxtNd );
+ SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
+ if( pCSttNd && pCEndNd )
+ pDoc->MoveAndJoin( aPam, aPos, IDocumentContentOperations::DOC_MOVEDEFAULT );
+ else
+ {
+ if( pCSttNd && !pCEndNd )
+ bDelLastPara = sal_True;
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ }
+ else
+ {
+ pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode );
+
+ SwPosition aPos( *pSttNd->EndOfSectionNode() );
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ }
+ pCntntSect = new SwNodeIndex( *pSttNd );
+
+ if( pStt == GetPoint() )
+ Exchange();
+
+ DeleteMark();
+ }
+ else
+ InvalidateRange();
+}
+
+void SwRedline::CopyToSection()
+{
+ if( !pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ SwStartNode* pSttNd;
+ SwDoc* pDoc = GetDoc();
+ SwNodes& rNds = pDoc->GetNodes();
+
+ sal_Bool bSaveCopyFlag = pDoc->IsCopyIsMove(),
+ bSaveRdlMoveFlg = pDoc->IsRedlineMove();
+ pDoc->SetCopyIsMove( sal_True );
+
+ // #100619# The IsRedlineMove() flag causes the behaviour of the
+ // SwDoc::_CopyFlyInFly method to change, which will eventually be
+ // called by the pDoc->Copy line below (through SwDoc::_Copy,
+ // SwDoc::CopyWithFlyInFly). This rather obscure bugfix was introduced
+ // for #63198# and #64896#, and apparently never really worked.
+ pDoc->SetRedlineMove( pStt->nContent == 0 );
+
+ if( pCSttNd )
+ {
+ SwTxtFmtColl* pColl = (pCSttNd && pCSttNd->IsTxtNode() )
+ ? ((SwTxtNode*)pCSttNd)->GetTxtColl()
+ : pDoc->GetTxtCollFromPool(
+ RES_POOLCOLL_STANDARD );
+
+ pSttNd = rNds.MakeTextSection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode, pColl );
+
+ SwNodeIndex aNdIdx( *pSttNd, 1 );
+ SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode();
+ SwPosition aPos( aNdIdx, SwIndex( pTxtNd ));
+ pDoc->CopyRange( *this, aPos, false );
+
+ // JP 08.10.98: die Vorlage vom EndNode ggfs. mit uebernehmen
+ // - ist im Doc::Copy nicht erwuenscht
+ if( pCEndNd && pCEndNd != pCSttNd )
+ {
+ SwCntntNode* pDestNd = aPos.nNode.GetNode().GetCntntNode();
+ if( pDestNd )
+ {
+ if( pDestNd->IsTxtNode() && pCEndNd->IsTxtNode() )
+ ((SwTxtNode*)pCEndNd)->CopyCollFmt(
+ *(SwTxtNode*)pDestNd );
+ else
+ pDestNd->ChgFmtColl( pCEndNd->GetFmtColl() );
+ }
+ }
+ }
+ else
+ {
+ pSttNd = rNds.MakeEmptySection( SwNodeIndex( rNds.GetEndOfRedlines() ),
+ SwNormalStartNode );
+
+ if( pCEndNd )
+ {
+ SwPosition aPos( *pSttNd->EndOfSectionNode() );
+ pDoc->CopyRange( *this, aPos, false );
+ }
+ else
+ {
+ SwNodeIndex aInsPos( *pSttNd->EndOfSectionNode() );
+ SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 );
+ pDoc->CopyWithFlyInFly( aRg, 0, aInsPos );
+ }
+ }
+ pCntntSect = new SwNodeIndex( *pSttNd );
+
+ pDoc->SetCopyIsMove( bSaveCopyFlag );
+ pDoc->SetRedlineMove( bSaveRdlMoveFlg );
+ }
+}
+
+void SwRedline::DelCopyOfSection()
+{
+ if( pCntntSect )
+ {
+ const SwPosition* pStt = Start(),
+ * pEnd = pStt == GetPoint() ? GetMark() : GetPoint();
+
+ SwDoc* pDoc = GetDoc();
+ SwPaM aPam( *pStt, *pEnd );
+ SwCntntNode* pCSttNd = pStt->nNode.GetNode().GetCntntNode();
+ SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
+
+ if( !pCSttNd )
+ {
+ // damit die Indizies der anderen Redlines nicht mitverschoben
+ // werden, diese aufs Ende setzen (ist exclusive).
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
+ {
+ SwRedline* pRedl = rTbl[ n ];
+ if( pRedl->GetBound(sal_True) == *pStt )
+ pRedl->GetBound(sal_True) = *pEnd;
+ if( pRedl->GetBound(sal_False) == *pStt )
+ pRedl->GetBound(sal_False) = *pEnd;
+ }
+ }
+
+ if( pCSttNd && pCEndNd )
+ {
+ // --> OD 2009-08-20 #i100466#
+ // force a <join next> on <delete and join> operation
+ pDoc->DeleteAndJoin( aPam, true );
+ // <--
+ }
+ else if( pCSttNd || pCEndNd )
+ {
+ if( pCSttNd && !pCEndNd )
+ bDelLastPara = sal_True;
+ pDoc->DeleteRange( aPam );
+
+ if( bDelLastPara )
+ {
+ // #100611# To prevent dangling references to the paragraph to
+ // be deleted, redline that point into this paragraph should be
+ // moved to the new end position. Since redlines in the redline
+ // table are sorted and the pEnd position is an endnode (see
+ // bDelLastPara condition above), only redlines before the
+ // current ones can be affected.
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ sal_uInt16 n = rTbl.GetPos( this );
+ ASSERT( n != USHRT_MAX, "How strange. We don't exist!" );
+ for( sal_Bool bBreak = sal_False; !bBreak && n > 0; )
+ {
+ --n;
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *aPam.GetPoint() )
+ {
+ rTbl[ n ]->GetBound(sal_True) = *pEnd;
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *aPam.GetPoint() )
+ {
+ rTbl[ n ]->GetBound(sal_False) = *pEnd;
+ bBreak = sal_False;
+ }
+ }
+
+ SwPosition aEnd( *pEnd );
+ *GetPoint() = *pEnd;
+ *GetMark() = *pEnd;
+ DeleteMark();
+
+ aPam.GetBound( sal_True ).nContent.Assign( 0, 0 );
+ aPam.GetBound( sal_False ).nContent.Assign( 0, 0 );
+ aPam.DeleteMark();
+ pDoc->DelFullPara( aPam );
+ }
+ }
+ else
+ {
+ pDoc->DeleteRange( aPam );
+ }
+
+ if( pStt == GetPoint() )
+ Exchange();
+
+ DeleteMark();
+ }
+}
+
+void SwRedline::MoveFromSection()
+{
+ if( pCntntSect )
+ {
+ SwDoc* pDoc = GetDoc();
+ const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
+ SvPtrarr aBeforeArr( 16, 16 ), aBehindArr( 16, 16 );
+ sal_uInt16 nMyPos = rTbl.GetPos( this );
+ ASSERT( this, "this nicht im Array?" );
+ sal_Bool bBreak = sal_False;
+ sal_uInt16 n;
+
+ for( n = nMyPos+1; !bBreak && n < rTbl.Count(); ++n )
+ {
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_True);
+ aBehindArr.Insert( pTmp, aBehindArr.Count());
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_False);
+ aBehindArr.Insert( pTmp, aBehindArr.Count() );
+ bBreak = sal_False;
+ }
+ }
+ for( bBreak = sal_False, n = nMyPos; !bBreak && n ; )
+ {
+ --n;
+ bBreak = sal_True;
+ if( rTbl[ n ]->GetBound(sal_True) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_True);
+ aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
+ bBreak = sal_False;
+ }
+ if( rTbl[ n ]->GetBound(sal_False) == *GetPoint() )
+ {
+ void* pTmp = &rTbl[ n ]->GetBound(sal_False);
+ aBeforeArr.Insert( pTmp, aBeforeArr.Count() );
+ bBreak = sal_False;
+ }
+ }
+
+ // --> OD 2009-03-17 #i95711#
+ const SwNode* pKeptCntntSectNode( &pCntntSect->GetNode() );
+ // <--
+ {
+ SwPaM aPam( pCntntSect->GetNode(),
+ *pCntntSect->GetNode().EndOfSectionNode(), 1,
+ ( bDelLastPara ? -2 : -1 ) );
+ SwCntntNode* pCNd = aPam.GetCntntNode();
+ if( pCNd )
+ aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+ else
+ aPam.GetPoint()->nNode++;
+
+ SwFmtColl* pColl = pCNd && pCNd->Len() && aPam.GetPoint()->nNode !=
+ aPam.GetMark()->nNode
+ ? pCNd->GetFmtColl() : 0;
+
+ SwNodeIndex aNdIdx( GetPoint()->nNode, -1 );
+ sal_uInt16 nPos = GetPoint()->nContent.GetIndex();
+
+ SwPosition aPos( *GetPoint() );
+ if( bDelLastPara && *aPam.GetPoint() == *aPam.GetMark() )
+ {
+ aPos.nNode--;
+
+ pDoc->AppendTxtNode( aPos );
+ }
+ else
+ {
+ pDoc->MoveRange( aPam, aPos,
+ IDocumentContentOperations::DOC_MOVEALLFLYS );
+ }
+
+ SetMark();
+ *GetPoint() = aPos;
+ GetMark()->nNode = aNdIdx.GetIndex() + 1;
+ pCNd = GetMark()->nNode.GetNode().GetCntntNode();
+ GetMark()->nContent.Assign( pCNd, nPos );
+
+ if( bDelLastPara )
+ {
+ GetPoint()->nNode++;
+ GetPoint()->nContent.Assign( pCNd = GetCntntNode(), 0 );
+ bDelLastPara = sal_False;
+ }
+ else if( pColl )
+ pCNd = GetCntntNode();
+
+ if( pColl && pCNd )
+ pCNd->ChgFmtColl( pColl );
+ }
+ // --> OD 2009-03-17 #i95771#
+ // Under certain conditions the previous <SwDoc::Move(..)> has already
+ // remove the change tracking section of this <SwRedline> instance from
+ // the change tracking nodes area.
+ // Thus, check, if <pCntntSect> still points to the change tracking section
+ // by comparing it with the "indexed" <SwNode> instance copied before
+ // perform the intrinsic move.
+ // Note: Such condition is e.g. a "delete" change tracking only containing a table.
+ if ( &pCntntSect->GetNode() == pKeptCntntSectNode )
+ {
+ pDoc->DeleteSection( &pCntntSect->GetNode() );
+ }
+ // <--
+ delete pCntntSect, pCntntSect = 0;
+
+ // #100611# adjustment of redline table positions must take start and
+ // end into account, not point and mark.
+ for( n = 0; n < aBeforeArr.Count(); ++n )
+ *(SwPosition*)aBeforeArr[ n ] = *Start();
+ for( n = 0; n < aBehindArr.Count(); ++n )
+ *(SwPosition*)aBehindArr[ n ] = *End();
+ }
+ else
+ InvalidateRange();
+}
+
+// fuers Undo
+void SwRedline::SetContentIdx( const SwNodeIndex* pIdx )
+{
+ if( pIdx && !pCntntSect )
+ {
+ pCntntSect = new SwNodeIndex( *pIdx );
+ bIsVisible = sal_False;
+ }
+ else if( !pIdx && pCntntSect )
+ {
+ delete pCntntSect, pCntntSect = 0;
+ bIsVisible = sal_False;
+ }
+#ifdef DBG_UTIL
+ else
+ ASSERT( !this, "das ist keine gueltige Operation" );
+#endif
+}
+
+sal_Bool SwRedline::CanCombine( const SwRedline& rRedl ) const
+{
+ return IsVisible() && rRedl.IsVisible() &&
+ pRedlineData->CanCombine( *rRedl.pRedlineData );
+}
+
+void SwRedline::PushData( const SwRedline& rRedl, sal_Bool bOwnAsNext )
+{
+// SwRedlineData* pNew = new SwRedlineData( rRedl.GetType(),
+// rRedl.GetAuthor() );
+ SwRedlineData* pNew = new SwRedlineData( *rRedl.pRedlineData, sal_False );
+ if( bOwnAsNext )
+ {
+ pNew->pNext = pRedlineData;
+ pRedlineData = pNew;
+ }
+ else
+ {
+ pNew->pNext = pRedlineData->pNext;
+ pRedlineData->pNext = pNew;
+ }
+}
+
+sal_Bool SwRedline::PopData()
+{
+ if( !pRedlineData->pNext )
+ return sal_False;
+ SwRedlineData* pCur = pRedlineData;
+ pRedlineData = pCur->pNext;
+ pCur->pNext = 0;
+ delete pCur;
+ return sal_True;
+}
+
+sal_uInt16 SwRedline::GetStackCount() const
+{
+ sal_uInt16 nRet = 1;
+ for( SwRedlineData* pCur = pRedlineData; pCur->pNext; ++nRet )
+ pCur = pCur->pNext;
+ return nRet;
+}
+
+// -> #111827#
+sal_uInt16 SwRedline::GetAuthor( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).nAuthor;
+}
+
+const String& SwRedline::GetAuthorString( sal_uInt16 nPos ) const
+{
+ return SW_MOD()->GetRedlineAuthor(GetRedlineData(nPos).nAuthor);
+}
+
+const DateTime& SwRedline::GetTimeStamp( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).aStamp;
+}
+
+RedlineType_t SwRedline::GetRealType( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).eType;
+}
+
+const String& SwRedline::GetComment( sal_uInt16 nPos ) const
+{
+ return GetRedlineData(nPos).sComment;
+}
+// <- #111827#
+
+int SwRedline::operator==( const SwRedline& rCmp ) const
+{
+ return this == &rCmp;
+}
+
+int SwRedline::operator<( const SwRedline& rCmp ) const
+{
+ sal_Bool nResult = sal_False;
+
+ if (*Start() < *rCmp.Start())
+ nResult = sal_True;
+ else if (*Start() == *rCmp.Start())
+ if (*End() < *rCmp.End())
+ nResult = sal_True;
+
+ return nResult;
+}
+
+// -> #111827#
+const SwRedlineData & SwRedline::GetRedlineData(sal_uInt16 nPos) const
+{
+ SwRedlineData * pCur = pRedlineData;
+
+ while (nPos > 0 && NULL != pCur->pNext)
+ {
+ pCur = pCur->pNext;
+
+ nPos--;
+ }
+
+ ASSERT( 0 == nPos, "Pos angabe ist zu gross" );
+
+ return *pCur;
+}
+
+String SwRedline::GetDescr(sal_uInt16 nPos)
+{
+ String aResult;
+
+ // get description of redline data (e.g.: "insert $1")
+ aResult = GetRedlineData(nPos).GetDescr();
+
+ SwPaM * pPaM = NULL;
+ bool bDeletePaM = false;
+
+ // if this redline is visible the content is in this PaM
+ if (NULL == pCntntSect)
+ {
+ pPaM = this;
+ }
+ else // otherwise it is saved in pCntntSect
+ {
+ SwNodeIndex aTmpIdx( *pCntntSect->GetNode().EndOfSectionNode() );
+ pPaM = new SwPaM(*pCntntSect, aTmpIdx );
+ bDeletePaM = true;
+ }
+
+ // replace $1 in description by description of the redlines text
+ String aTmpStr;
+ aTmpStr += String(SW_RES(STR_START_QUOTE));
+ aTmpStr += ShortenString(pPaM->GetTxt(), nUndoStringLength,
+ String(SW_RES(STR_LDOTS)));
+ aTmpStr += String(SW_RES(STR_END_QUOTE));
+
+ SwRewriter aRewriter;
+ aRewriter.AddRule(UNDO_ARG1, aTmpStr);
+
+ aResult = aRewriter.Apply(aResult);
+
+ if (bDeletePaM)
+ delete pPaM;
+
+ return aResult;
+}
+// <- #111827#
+
+
+bool SwDoc::IsInRedlines(const SwNode & rNode) const
+{
+ SwPosition aPos(rNode);
+ SwNode & rEndOfRedlines = GetNodes().GetEndOfRedlines();
+ SwPaM aPam(SwPosition(*rEndOfRedlines.StartOfSectionNode()),
+ SwPosition(rEndOfRedlines));
+
+ return aPam.ContainsPosition(aPos) ? true : false;
+}