4274 lines
142 KiB
C++
4274 lines
142 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#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/crossedoutitem.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);
|
|
|
|
#ifdef DBG_UTIL
|
|
|
|
#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
|
|
static void lcl_CheckPosition( const SwPosition* pPos )
|
|
{
|
|
SwPosition aComparePos( *pPos );
|
|
aComparePos.nContent.Assign(
|
|
aComparePos.nNode.GetNode().GetCntntNode(), 0 );
|
|
OSL_ENSURE( pPos->nContent.GetIdxReg() ==
|
|
aComparePos.nContent.GetIdxReg(),
|
|
_ERROR_PREFIX "illegal position" );
|
|
|
|
SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
|
|
if( pTxtNode == NULL )
|
|
{
|
|
OSL_ENSURE( pPos->nContent == 0,
|
|
_ERROR_PREFIX "non-text-node with content" );
|
|
}
|
|
else
|
|
{
|
|
OSL_ENSURE( pPos->nContent >= 0 &&
|
|
pPos->nContent <= pTxtNode->Len(),
|
|
_ERROR_PREFIX "index behind text" );
|
|
}
|
|
}
|
|
|
|
static void lcl_CheckPam( const SwPaM* pPam )
|
|
{
|
|
OSL_ENSURE( 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.
|
|
static void lcl_CheckRedline( const SwDoc* pDoc )
|
|
{
|
|
const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
|
|
|
|
// verify valid redline positions
|
|
for( sal_uInt16 i = 0; i < rTbl.size(); ++i )
|
|
lcl_CheckPam( rTbl[ i ] );
|
|
|
|
for( sal_uInt16 j = 0; j < rTbl.size(); ++j )
|
|
{
|
|
// check for empty redlines
|
|
OSL_ENSURE( ( *(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.size(); ++n )
|
|
{
|
|
const SwRangeRedline* pPrev = rTbl[ n-1 ];
|
|
const SwRangeRedline* pCurrent = rTbl[ n ];
|
|
|
|
// check redline sorting
|
|
SAL_WARN_IF( *pPrev->Start() > *pCurrent->Start(), "sw",
|
|
_ERROR_PREFIX "not sorted correctly" );
|
|
|
|
// check for overlapping redlines
|
|
SAL_WARN_IF( *pPrev->End() > *pCurrent->Start(), "sw",
|
|
_ERROR_PREFIX "overlapping redlines" );
|
|
}
|
|
}
|
|
|
|
#define _CHECK_REDLINE( pDoc ) lcl_CheckRedline( pDoc );
|
|
|
|
void sw_DebugRedline( const SwDoc* pDoc )
|
|
{
|
|
static sal_uInt16 nWatch = 0;
|
|
const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
|
|
for( sal_uInt16 n = 0; n < rTbl.size(); ++n )
|
|
{
|
|
sal_uInt16 nDummy = 0;
|
|
const SwRangeRedline* pCurrent = rTbl[ n ];
|
|
const SwRangeRedline* pNext = n+1 < (sal_uInt16)rTbl.size() ? rTbl[ n+1 ] : 0;
|
|
if( pCurrent == pNext )
|
|
++nDummy;
|
|
if( n == nWatch )
|
|
++nDummy; // Possible debugger breakpoint
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
#define _CHECK_REDLINE( pDoc )
|
|
|
|
#endif
|
|
|
|
RedlineMode_t SwDoc::GetRedlineMode() const
|
|
{
|
|
return meRedlineMode;
|
|
}
|
|
|
|
void SwDoc::SetRedlineMode( RedlineMode_t eMode )
|
|
{
|
|
if( meRedlineMode != eMode )
|
|
{
|
|
if( (nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode)
|
|
|| 0 == (nsRedlineMode_t::REDLINE_SHOW_MASK & eMode) )
|
|
{
|
|
bool bSaveInXMLImportFlag = IsInXMLImport();
|
|
SetInXMLImport( false );
|
|
// and then hide/display everything
|
|
void (SwRangeRedline::*pFnc)( sal_uInt16 ) = 0;
|
|
|
|
switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode )
|
|
{
|
|
case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE :
|
|
pFnc = &SwRangeRedline::Show;
|
|
break;
|
|
case nsRedlineMode_t::REDLINE_SHOW_INSERT:
|
|
pFnc = &SwRangeRedline::Hide;
|
|
break;
|
|
case nsRedlineMode_t::REDLINE_SHOW_DELETE:
|
|
pFnc = &SwRangeRedline::ShowOriginal;
|
|
break;
|
|
|
|
default:
|
|
pFnc = &SwRangeRedline::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 < mpRedlineTbl->size(); ++i )
|
|
((*mpRedlineTbl)[ i ]->*pFnc)( nLoop );
|
|
_CHECK_REDLINE( this )
|
|
SetInXMLImport( bSaveInXMLImportFlag );
|
|
}
|
|
meRedlineMode = eMode;
|
|
SetModified();
|
|
}
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
bool SwDoc::IsRedlineOn() const
|
|
{
|
|
return IDocumentRedlineAccess::IsRedlineOn(meRedlineMode);
|
|
}
|
|
|
|
bool SwDoc::IsIgnoreRedline() const
|
|
{
|
|
return (nsRedlineMode_t::REDLINE_IGNORE & meRedlineMode);
|
|
}
|
|
|
|
void SwDoc::SetRedlineMode_intern(RedlineMode_t eMode)
|
|
{
|
|
meRedlineMode = eMode;
|
|
}
|
|
|
|
const SwRedlineTbl& SwDoc::GetRedlineTbl() const
|
|
{
|
|
return *mpRedlineTbl;
|
|
}
|
|
|
|
const SwExtraRedlineTbl& SwDoc::GetExtraRedlineTbl() const
|
|
{
|
|
return *mpExtraRedlineTbl;
|
|
}
|
|
|
|
SwExtraRedlineTbl::~SwExtraRedlineTbl()
|
|
{
|
|
DeleteAndDestroyAll();
|
|
}
|
|
|
|
SwExtraRedlineTbl& SwDoc::GetExtraRedlineTbl()
|
|
{
|
|
return *mpExtraRedlineTbl;
|
|
}
|
|
|
|
bool SwDoc::HasExtraRedlineTbl() const
|
|
{
|
|
return mpExtraRedlineTbl ? true : false;
|
|
}
|
|
|
|
bool SwDoc::IsRedlineMove() const
|
|
{
|
|
return mbIsRedlineMove;
|
|
}
|
|
|
|
void SwDoc::SetRedlineMove(bool bFlag)
|
|
{
|
|
mbIsRedlineMove = bFlag;
|
|
}
|
|
|
|
const uno::Sequence <sal_Int8>& SwDoc::GetRedlinePassword() const
|
|
{
|
|
return maRedlinePasswd;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
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 means Text not "polluted" by Redlines.
|
|
|
|
Behaviour of Insert-Redline:
|
|
- in the Text - insert Redline Object
|
|
- in InsertRedline (own) - ignore, existing is extended
|
|
- in InsertRedline (others) - split up InsertRedline and
|
|
insert Redline Object
|
|
- in DeleteRedline - split up DeleteRedline or
|
|
move at the end/beginning
|
|
|
|
Behaviour of Delete-Redline:
|
|
- in the Text - insert Redline Object
|
|
- in DeleteRedline (own/others) - ignore
|
|
- in InsertRedline (own) - ignore, but delete character
|
|
- in InsertRedline (others) - split up InsertRedline and
|
|
insert Redline Object
|
|
- Text and own Insert overlap - delete Text in the own Insert,
|
|
extend in the other Text
|
|
(up to the Insert!)
|
|
- Text and other Insert overlap - insert Redline Object, the
|
|
other Insert is overlapped by
|
|
the Delete
|
|
*/
|
|
bool SwDoc::AppendRedline( SwRangeRedline* pNewRedl, bool bCallDelete )
|
|
{
|
|
bool bMerged = false;
|
|
_CHECK_REDLINE( this )
|
|
|
|
if (IsRedlineOn() && !IsShowOriginal(meRedlineMode))
|
|
{
|
|
pNewRedl->InvalidateRange();
|
|
|
|
if( mbIsAutoFmtRedline )
|
|
{
|
|
pNewRedl->SetAutoFmtFlag();
|
|
if( mpAutoFmtRedlnComment && !mpAutoFmtRedlnComment->isEmpty() )
|
|
{
|
|
pNewRedl->SetComment( *mpAutoFmtRedlnComment );
|
|
pNewRedl->SetSeqNo( mnAutoFmtRedlnCommentNo );
|
|
}
|
|
}
|
|
|
|
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 )
|
|
{
|
|
OSL_ENSURE( false, "Redline start: non-text-node with content" );
|
|
pStt->nContent = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( pStt->nContent > pTxtNode->Len() )
|
|
{
|
|
OSL_ENSURE( false, "Redline start: index behind text" );
|
|
pStt->nContent = pTxtNode->Len();
|
|
}
|
|
}
|
|
pTxtNode = pEnd->nNode.GetNode().GetTxtNode();
|
|
if( pTxtNode == NULL )
|
|
{
|
|
if( pEnd->nContent > 0 )
|
|
{
|
|
OSL_ENSURE( false, "Redline end: non-text-node with content" );
|
|
pEnd->nContent = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( pEnd->nContent > pTxtNode->Len() )
|
|
{
|
|
OSL_ENSURE( false, "Redline end: index behind text" );
|
|
pEnd->nContent = pTxtNode->Len();
|
|
}
|
|
}
|
|
}
|
|
if( ( *pStt == *pEnd ) &&
|
|
( pNewRedl->GetContentIdx() == NULL ) )
|
|
{ // Do not insert empty redlines
|
|
delete pNewRedl;
|
|
return false;
|
|
}
|
|
bool bCompress = false;
|
|
sal_uInt16 n = 0;
|
|
// look up the first Redline for the starting position
|
|
if( !GetRedline( *pStt, &n ) && n )
|
|
--n;
|
|
bool bDec = false;
|
|
|
|
for( ; pNewRedl && n < mpRedlineTbl->size(); bDec ? n : ++n )
|
|
{
|
|
bDec = false;
|
|
|
|
SwRangeRedline* pRedl = (*mpRedlineTbl)[ 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 ) )
|
|
{
|
|
mpRedlineTbl->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;
|
|
|
|
// Merge if applicable?
|
|
if( (( POS_BEHIND == eCmpPos &&
|
|
IsPrevPos( *pREnd, *pStt ) ) ||
|
|
( POS_COLLIDE_START == eCmpPos ) ||
|
|
( POS_OVERLAP_BEHIND == eCmpPos ) ) &&
|
|
pRedl->CanCombine( *pNewRedl ) &&
|
|
( n+1 >= (sal_uInt16)mpRedlineTbl->size() ||
|
|
( *(*mpRedlineTbl)[ n+1 ]->Start() >= *pEnd &&
|
|
*(*mpRedlineTbl)[ n+1 ]->Start() != *pREnd ) ) )
|
|
{
|
|
pRedl->SetEnd( *pEnd, pREnd );
|
|
if( !pRedl->HasValidRange() )
|
|
{
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
}
|
|
|
|
bMerged = true;
|
|
bDelete = true;
|
|
}
|
|
else if( (( POS_BEFORE == eCmpPos &&
|
|
IsPrevPos( *pEnd, *pRStt ) ) ||
|
|
( POS_COLLIDE_END == eCmpPos ) ||
|
|
( POS_OVERLAP_BEFORE == eCmpPos ) ) &&
|
|
pRedl->CanCombine( *pNewRedl ) &&
|
|
( !n ||
|
|
*(*mpRedlineTbl)[ n-1 ]->End() != *pRStt ))
|
|
{
|
|
pRedl->SetStart( *pStt, pRStt );
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
|
|
bMerged = true;
|
|
bDelete = true;
|
|
}
|
|
else if ( POS_OUTSIDE == eCmpPos )
|
|
{
|
|
// own insert-over-insert redlines:
|
|
// just scrap the inside ones
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
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 = true;
|
|
}
|
|
}
|
|
else if( POS_INSIDE == eCmpPos )
|
|
{
|
|
// split up
|
|
if( *pEnd != *pREnd )
|
|
{
|
|
SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
|
|
pCpy->SetStart( *pEnd );
|
|
mpRedlineTbl->Insert( pCpy );
|
|
}
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
if( ( *pStt == *pRStt ) &&
|
|
( pRedl->GetContentIdx() == NULL ) )
|
|
{
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
else if( !pRedl->HasValidRange() )
|
|
{
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
}
|
|
}
|
|
else if ( POS_OUTSIDE == eCmpPos )
|
|
{
|
|
// 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
|
|
SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl );
|
|
pSplit->SetEnd( *pRStt );
|
|
pNewRedl->SetStart( *pREnd );
|
|
mpRedlineTbl->Insert( pSplit );
|
|
if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
|
|
{
|
|
delete pNewRedl;
|
|
pNewRedl = 0;
|
|
bCompress = true;
|
|
}
|
|
}
|
|
else if ( POS_OVERLAP_BEHIND == eCmpPos )
|
|
{
|
|
// handle overlapping redlines in broken documents
|
|
pNewRedl->SetStart( *pREnd );
|
|
}
|
|
else if ( POS_OVERLAP_BEFORE == eCmpPos )
|
|
{
|
|
// 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 )
|
|
{
|
|
// split up
|
|
if( *pEnd != *pREnd )
|
|
{
|
|
SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
|
|
pCpy->SetStart( *pEnd );
|
|
mpRedlineTbl->Insert( pCpy );
|
|
}
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
if( ( *pStt == *pRStt ) &&
|
|
( pRedl->GetContentIdx() == NULL ) )
|
|
{
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
else if( !pRedl->HasValidRange() )
|
|
{
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl, n );
|
|
}
|
|
}
|
|
else if ( POS_OUTSIDE == eCmpPos )
|
|
{
|
|
// 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
|
|
SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl );
|
|
pSplit->SetEnd( *pRStt );
|
|
pNewRedl->SetStart( *pREnd );
|
|
mpRedlineTbl->Insert( pSplit );
|
|
if( *pStt == *pEnd && pNewRedl->GetContentIdx() == NULL )
|
|
{
|
|
delete pNewRedl;
|
|
pNewRedl = 0;
|
|
bCompress = true;
|
|
}
|
|
}
|
|
else if ( POS_EQUAL == eCmpPos )
|
|
{
|
|
// handle identical redlines in broken documents
|
|
// delete old (delete) redline
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
else if ( POS_OVERLAP_BEHIND == eCmpPos )
|
|
{ // Another workaround for broken redlines
|
|
pNewRedl->SetStart( *pREnd );
|
|
}
|
|
break;
|
|
case nsRedlineType_t::REDLINE_FORMAT:
|
|
switch( eCmpPos )
|
|
{
|
|
case POS_OVERLAP_BEFORE:
|
|
pRedl->SetStart( *pEnd, pRStt );
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl, n );
|
|
bDec = true;
|
|
break;
|
|
|
|
case POS_OVERLAP_BEHIND:
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
|
|
{
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
break;
|
|
|
|
case POS_EQUAL:
|
|
case POS_OUTSIDE:
|
|
// Overlaps the current one completely or has the
|
|
// same dimension, delete the old one
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
break;
|
|
|
|
case POS_INSIDE:
|
|
// Overlaps the current one completely,
|
|
// split or shorten the new one
|
|
if( *pEnd != *pREnd )
|
|
{
|
|
if( *pEnd != *pRStt )
|
|
{
|
|
SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
|
|
pNew->SetStart( *pEnd );
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
if( *pStt == *pRStt && pRedl->GetContentIdx() == NULL )
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
AppendRedline( pNew, bCallDelete );
|
|
n = 0; // re-initialize
|
|
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:
|
|
{
|
|
// Overlaps the current one completely,
|
|
// split the new one
|
|
if( *pEnd != *pREnd )
|
|
{
|
|
SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl );
|
|
pNew->SetStart( *pREnd );
|
|
pNewRedl->SetEnd( *pRStt, pEnd );
|
|
AppendRedline( pNew, bCallDelete );
|
|
n = 0; // re-initialize
|
|
bDec = true;
|
|
}
|
|
else
|
|
pNewRedl->SetEnd( *pRStt, pEnd );
|
|
}
|
|
break;
|
|
|
|
case POS_INSIDE:
|
|
case POS_EQUAL:
|
|
delete pNewRedl, pNewRedl = 0;
|
|
bCompress = true;
|
|
break;
|
|
|
|
case POS_OVERLAP_BEFORE:
|
|
case POS_OVERLAP_BEHIND:
|
|
if( pRedl->IsOwnRedline( *pNewRedl ) &&
|
|
pRedl->CanCombine( *pNewRedl ))
|
|
{
|
|
// If that's the case we can merge it, meaning
|
|
// the new one covers this well
|
|
if( POS_OVERLAP_BEHIND == eCmpPos )
|
|
pNewRedl->SetStart( *pRStt, pStt );
|
|
else
|
|
pNewRedl->SetEnd( *pREnd, pEnd );
|
|
mpRedlineTbl->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 ) &&
|
|
pRedl->CanCombine( *pNewRedl ) )
|
|
{
|
|
if( IsHideChanges( meRedlineMode ))
|
|
{
|
|
// Before we can merge, we make it visible!
|
|
// We insert temporarily so that pNew is
|
|
// also dealt with when moving the indices.
|
|
mpRedlineTbl->Insert( pNewRedl );
|
|
pRedl->Show();
|
|
mpRedlineTbl->Remove( pNewRedl );
|
|
pRStt = pRedl->Start();
|
|
pREnd = pRedl->End();
|
|
}
|
|
|
|
// If that's the case we can merge it, meaning
|
|
// the new one covers this well
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
mpRedlineTbl->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 = meRedlineMode;
|
|
if( !( eOld & nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &&
|
|
pRedl->IsOwnRedline( *pNewRedl ) )
|
|
{
|
|
|
|
// Set to NONE, so that the Delete::Redo merges the Redline data correctly!
|
|
// The ShowMode needs to be retained!
|
|
meRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
|
|
switch( eCmpPos )
|
|
{
|
|
case POS_EQUAL:
|
|
bCompress = true;
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
// no break!
|
|
|
|
case POS_INSIDE:
|
|
if( bCallDelete )
|
|
{
|
|
meRedlineMode = (RedlineMode_t)(meRedlineMode | nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES);
|
|
|
|
// 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 = true;
|
|
}
|
|
delete pNewRedl, pNewRedl = 0;
|
|
break;
|
|
|
|
case POS_OUTSIDE:
|
|
{
|
|
mpRedlineTbl->Remove( n );
|
|
bDec = true;
|
|
// We insert temporarily so that pNew is
|
|
// also dealt with when moving the indices.
|
|
if( bCallDelete )
|
|
{
|
|
mpRedlineTbl->Insert( pNewRedl );
|
|
DeleteAndJoin( *pRedl );
|
|
if( !mpRedlineTbl->Remove( pNewRedl ) )
|
|
pNewRedl = 0;
|
|
}
|
|
delete pRedl;
|
|
}
|
|
break;
|
|
|
|
case POS_OVERLAP_BEFORE:
|
|
{
|
|
SwPaM aPam( *pRStt, *pEnd );
|
|
|
|
if( *pEnd == *pREnd )
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
else
|
|
{
|
|
pRedl->SetStart( *pEnd, pRStt );
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl, n );
|
|
}
|
|
|
|
if( bCallDelete )
|
|
{
|
|
// We insert temporarily so that pNew is
|
|
// also dealt with when moving the indices.
|
|
mpRedlineTbl->Insert( pNewRedl );
|
|
DeleteAndJoin( aPam );
|
|
if( !mpRedlineTbl->Remove( pNewRedl ) )
|
|
pNewRedl = 0;
|
|
n = 0; // re-initialize
|
|
}
|
|
bDec = true;
|
|
}
|
|
break;
|
|
|
|
case POS_OVERLAP_BEHIND:
|
|
{
|
|
SwPaM aPam( *pStt, *pREnd );
|
|
|
|
if( *pStt == *pRStt )
|
|
{
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
else
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
|
|
if( bCallDelete )
|
|
{
|
|
// We insert temporarily so that pNew is
|
|
// also dealt with when moving the indices.
|
|
mpRedlineTbl->Insert( pNewRedl );
|
|
DeleteAndJoin( aPam );
|
|
if( !mpRedlineTbl->Remove( pNewRedl ) )
|
|
pNewRedl = 0;
|
|
n = 0; // re-initialize
|
|
bDec = true;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
meRedlineMode = 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.
|
|
SwRangeRedline* pNew = 0;
|
|
|
|
switch( eCmpPos )
|
|
{
|
|
case POS_EQUAL:
|
|
{
|
|
pRedl->PushData( *pNewRedl );
|
|
delete pNewRedl, pNewRedl = 0;
|
|
if( IsHideChanges( meRedlineMode ))
|
|
pRedl->Hide();
|
|
bCompress = true;
|
|
}
|
|
break;
|
|
|
|
case POS_INSIDE:
|
|
{
|
|
if( *pRStt == *pStt )
|
|
{
|
|
// #i97421#
|
|
// redline w/out extent loops
|
|
if (*pStt != *pEnd)
|
|
{
|
|
pNewRedl->PushData( *pRedl, sal_False );
|
|
pRedl->SetStart( *pEnd, pRStt );
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl, n );
|
|
bDec = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNewRedl->PushData( *pRedl, sal_False );
|
|
if( *pREnd != *pEnd )
|
|
{
|
|
pNew = new SwRangeRedline( *pRedl );
|
|
pNew->SetStart( *pEnd );
|
|
}
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
if( !pRedl->HasValidRange() )
|
|
{
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl, n );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case POS_OUTSIDE:
|
|
{
|
|
pRedl->PushData( *pNewRedl );
|
|
if( *pEnd == *pREnd )
|
|
pNewRedl->SetEnd( *pRStt, pEnd );
|
|
else
|
|
{
|
|
pNew = new SwRangeRedline( *pNewRedl );
|
|
pNew->SetEnd( *pRStt );
|
|
pNewRedl->SetStart( *pREnd, pStt );
|
|
}
|
|
bCompress = true;
|
|
}
|
|
break;
|
|
|
|
case POS_OVERLAP_BEFORE:
|
|
{
|
|
if( *pEnd == *pREnd )
|
|
{
|
|
pRedl->PushData( *pNewRedl );
|
|
pNewRedl->SetEnd( *pRStt, pEnd );
|
|
if( IsHideChanges( meRedlineMode ))
|
|
{
|
|
mpRedlineTbl->Insert( pNewRedl );
|
|
pRedl->Hide();
|
|
mpRedlineTbl->Remove( pNewRedl );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNew = new SwRangeRedline( *pRedl );
|
|
pNew->PushData( *pNewRedl );
|
|
pNew->SetEnd( *pEnd );
|
|
pNewRedl->SetEnd( *pRStt, pEnd );
|
|
pRedl->SetStart( *pNew->End(), pRStt ) ;
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
bDec = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case POS_OVERLAP_BEHIND:
|
|
{
|
|
if( *pStt == *pRStt )
|
|
{
|
|
pRedl->PushData( *pNewRedl );
|
|
pNewRedl->SetStart( *pREnd, pStt );
|
|
if( IsHideChanges( meRedlineMode ))
|
|
{
|
|
mpRedlineTbl->Insert( pNewRedl );
|
|
pRedl->Hide();
|
|
mpRedlineTbl->Remove( pNewRedl );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNew = new SwRangeRedline( *pRedl );
|
|
pNew->PushData( *pNewRedl );
|
|
pNew->SetStart( *pStt );
|
|
pNewRedl->SetStart( *pREnd, pStt );
|
|
pRedl->SetEnd( *pNew->Start(), pREnd );
|
|
if( !pRedl->HasValidRange() )
|
|
{
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// insert the pNew part (if it exists)
|
|
if( pNew )
|
|
{
|
|
mpRedlineTbl->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.
|
|
// OSL_ENSURE( 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 );
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl, n );
|
|
bDec = true;
|
|
break;
|
|
|
|
case POS_OVERLAP_BEHIND:
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
break;
|
|
|
|
case POS_EQUAL:
|
|
case POS_OUTSIDE:
|
|
// Overlaps the current one completely or has the
|
|
// same dimension, delete the old one
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
break;
|
|
|
|
case POS_INSIDE:
|
|
// Overlaps the current one completely,
|
|
// split or shorten the new one
|
|
if( *pEnd != *pREnd )
|
|
{
|
|
if( *pEnd != *pRStt )
|
|
{
|
|
SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
|
|
pNew->SetStart( *pEnd );
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
if( ( *pStt == *pRStt ) &&
|
|
( pRedl->GetContentIdx() == NULL ) )
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
AppendRedline( pNew, bCallDelete );
|
|
n = 0; // re-initialize
|
|
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:
|
|
// Overlaps the current one completely,
|
|
// split or shorten the new one
|
|
if( *pEnd != *pREnd )
|
|
{
|
|
if( *pEnd != *pRStt )
|
|
{
|
|
SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl );
|
|
pNew->SetStart( *pREnd );
|
|
pNewRedl->SetEnd( *pRStt, pEnd );
|
|
AppendRedline( pNew, bCallDelete );
|
|
n = 0; // re-initialize
|
|
bDec = true;
|
|
}
|
|
}
|
|
else
|
|
pNewRedl->SetEnd( *pRStt, pEnd );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case nsRedlineType_t::REDLINE_FORMAT:
|
|
switch( eCmpPos )
|
|
{
|
|
case POS_OUTSIDE:
|
|
case POS_EQUAL:
|
|
{
|
|
// Overlaps the current one completely or has the
|
|
// same dimension, delete the old one
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
break;
|
|
|
|
case POS_INSIDE:
|
|
if( pRedl->IsOwnRedline( *pNewRedl ) &&
|
|
pRedl->CanCombine( *pNewRedl ))
|
|
// own one can be ignored completely
|
|
delete pNewRedl, pNewRedl = 0;
|
|
|
|
else if( *pREnd == *pEnd )
|
|
// or else only shorten the current one
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
else if( *pRStt == *pStt )
|
|
{
|
|
// or else only shorten the current one
|
|
pRedl->SetStart( *pEnd, pRStt );
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl, n );
|
|
bDec = true;
|
|
}
|
|
else
|
|
{
|
|
// If it lies completely within the current one
|
|
// we need to split it
|
|
SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
|
|
pNew->SetStart( *pEnd );
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
AppendRedline( pNew, bCallDelete );
|
|
n = 0; // re-initialize
|
|
bDec = true;
|
|
}
|
|
break;
|
|
|
|
case POS_OVERLAP_BEFORE:
|
|
case POS_OVERLAP_BEHIND:
|
|
if( pRedl->IsOwnRedline( *pNewRedl ) &&
|
|
pRedl->CanCombine( *pNewRedl ))
|
|
{
|
|
// If that's the case we can merge it, meaning
|
|
// the new one covers this well
|
|
if( POS_OVERLAP_BEHIND == eCmpPos )
|
|
pNewRedl->SetStart( *pRStt, pStt );
|
|
else
|
|
pNewRedl->SetEnd( *pREnd, pEnd );
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = false;
|
|
}
|
|
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 &&
|
|
*(*mpRedlineTbl)[ n-1 ]->End() < *pStt )
|
|
{
|
|
// If that's the case we can merge it, meaning
|
|
// the new one covers this well
|
|
pNewRedl->SetEnd( *pREnd, pEnd );
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
break;
|
|
case POS_COLLIDE_START:
|
|
if( pRedl->IsOwnRedline( *pNewRedl ) &&
|
|
pRedl->CanCombine( *pNewRedl ) &&
|
|
n+1 < (sal_uInt16)mpRedlineTbl->size() &&
|
|
*(*mpRedlineTbl)[ n+1 ]->Start() < *pEnd )
|
|
{
|
|
// If that's the case we can merge it, meaning
|
|
// the new one covers this well
|
|
pNewRedl->SetStart( *pRStt, pStt );
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
bDec = true;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case nsRedlineType_t::REDLINE_FMTCOLL:
|
|
// How should we behave here?
|
|
// insert as is
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( pNewRedl )
|
|
{
|
|
if( ( *pStt == *pEnd ) &&
|
|
( pNewRedl->GetContentIdx() == NULL ) )
|
|
{ // Do not insert empty redlines
|
|
delete pNewRedl;
|
|
pNewRedl = 0;
|
|
}
|
|
else
|
|
mpRedlineTbl->Insert( pNewRedl );
|
|
}
|
|
|
|
if( bCompress )
|
|
CompressRedlines();
|
|
}
|
|
else
|
|
{
|
|
if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
|
|
{
|
|
RedlineMode_t eOld = meRedlineMode;
|
|
// Set to NONE, so that the Delete::Redo merges the Redline data correctly!
|
|
// The ShowMode needs to be retained!
|
|
meRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
|
|
DeleteAndJoin( *pNewRedl );
|
|
meRedlineMode = eOld;
|
|
}
|
|
delete pNewRedl, pNewRedl = 0;
|
|
}
|
|
_CHECK_REDLINE( this )
|
|
|
|
return ( 0 != pNewRedl ) || bMerged;
|
|
}
|
|
|
|
void SwDoc::CompressRedlines()
|
|
{
|
|
_CHECK_REDLINE( this )
|
|
|
|
void (SwRangeRedline::*pFnc)(sal_uInt16) = 0;
|
|
switch( nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode )
|
|
{
|
|
case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
|
|
pFnc = &SwRangeRedline::Show;
|
|
break;
|
|
case nsRedlineMode_t::REDLINE_SHOW_INSERT:
|
|
pFnc = &SwRangeRedline::Hide;
|
|
break;
|
|
}
|
|
|
|
// Try to merge identical ones
|
|
for( sal_uInt16 n = 1; n < mpRedlineTbl->size(); ++n )
|
|
{
|
|
SwRangeRedline* pPrev = (*mpRedlineTbl)[ n-1 ],
|
|
* pCur = (*mpRedlineTbl)[ 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() )
|
|
{
|
|
// we then can merge them
|
|
pPrev->Show();
|
|
pCur->Show();
|
|
|
|
pPrev->SetEnd( *pCur->End() );
|
|
mpRedlineTbl->DeleteAndDestroy( n );
|
|
--n;
|
|
if( pFnc )
|
|
(pPrev->*pFnc)(0);
|
|
}
|
|
}
|
|
_CHECK_REDLINE( this )
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
bool SwDoc::SplitRedline( const SwPaM& rRange )
|
|
{
|
|
bool bChg = false;
|
|
sal_uInt16 n = 0;
|
|
const SwPosition* pStt = rRange.Start(),
|
|
* pEnd = pStt == rRange.GetPoint() ? rRange.GetMark()
|
|
: rRange.GetPoint();
|
|
GetRedline( *pStt, &n );
|
|
for( ; n < mpRedlineTbl->size() ; ++n )
|
|
{
|
|
SwRangeRedline* pTmp = (*mpRedlineTbl)[ n ];
|
|
SwPosition* pTStt = pTmp->Start(),
|
|
* pTEnd = pTStt == pTmp->GetPoint() ? pTmp->GetMark()
|
|
: pTmp->GetPoint();
|
|
if( *pTStt <= *pStt && *pStt <= *pTEnd &&
|
|
*pTStt <= *pEnd && *pEnd <= *pTEnd )
|
|
{
|
|
bChg = true;
|
|
int nn = 0;
|
|
if( *pStt == *pTStt )
|
|
nn += 1;
|
|
if( *pEnd == *pTEnd )
|
|
nn += 2;
|
|
|
|
SwRangeRedline* pNew = 0;
|
|
switch( nn )
|
|
{
|
|
case 0:
|
|
pNew = new SwRangeRedline( *pTmp );
|
|
pTmp->SetEnd( *pStt, pTEnd );
|
|
pNew->SetStart( *pEnd );
|
|
break;
|
|
|
|
case 1:
|
|
*pTStt = *pEnd;
|
|
break;
|
|
|
|
case 2:
|
|
*pTEnd = *pStt;
|
|
break;
|
|
|
|
case 3:
|
|
pTmp->InvalidateRange();
|
|
mpRedlineTbl->DeleteAndDestroy( n-- );
|
|
pTmp = 0;
|
|
break;
|
|
}
|
|
if( pTmp && !pTmp->HasValidRange() )
|
|
{
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pTmp, n );
|
|
}
|
|
if( pNew )
|
|
mpRedlineTbl->Insert( pNew, n );
|
|
}
|
|
else if( *pEnd < *pTStt )
|
|
break;
|
|
}
|
|
return bChg;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
bool SwDoc::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
|
|
sal_uInt16 nDelType )
|
|
{
|
|
if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & meRedlineMode ||
|
|
!rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
|
|
return false;
|
|
|
|
bool bChg = 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 < mpRedlineTbl->size() ; ++n )
|
|
{
|
|
SwRangeRedline* pRedl = (*mpRedlineTbl)[ n ];
|
|
if( USHRT_MAX != nDelType && nDelType != pRedl->GetType() )
|
|
continue;
|
|
|
|
SwPosition* pRStt = pRedl->Start(),
|
|
* pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
|
|
: pRedl->GetPoint();
|
|
switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
|
|
{
|
|
case POS_EQUAL:
|
|
case POS_OUTSIDE:
|
|
pRedl->InvalidateRange();
|
|
mpRedlineTbl->DeleteAndDestroy( n-- );
|
|
bChg = true;
|
|
break;
|
|
|
|
case POS_OVERLAP_BEFORE:
|
|
pRedl->InvalidateRange();
|
|
pRedl->SetStart( *pEnd, pRStt );
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
--n;
|
|
break;
|
|
|
|
case POS_OVERLAP_BEHIND:
|
|
pRedl->InvalidateRange();
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
if( !pRedl->HasValidRange() )
|
|
{
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
--n;
|
|
}
|
|
break;
|
|
|
|
case POS_INSIDE:
|
|
{
|
|
// this one needs to be splitted
|
|
pRedl->InvalidateRange();
|
|
if( *pRStt == *pStt )
|
|
{
|
|
pRedl->SetStart( *pEnd, pRStt );
|
|
// re-insert
|
|
mpRedlineTbl->Remove( n );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
--n;
|
|
}
|
|
else
|
|
{
|
|
SwRangeRedline* pCpy;
|
|
if( *pREnd != *pEnd )
|
|
{
|
|
pCpy = new SwRangeRedline( *pRedl );
|
|
pCpy->SetStart( *pEnd );
|
|
}
|
|
else
|
|
pCpy = 0;
|
|
pRedl->SetEnd( *pStt, pREnd );
|
|
if( !pRedl->HasValidRange() )
|
|
{
|
|
// re-insert
|
|
mpRedlineTbl->Remove( pRedl );
|
|
mpRedlineTbl->Insert( pRedl );
|
|
--n;
|
|
}
|
|
if( pCpy )
|
|
mpRedlineTbl->Insert( pCpy );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case POS_COLLIDE_END:
|
|
case POS_BEFORE:
|
|
n = mpRedlineTbl->size();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( bChg )
|
|
SetModified();
|
|
|
|
return bChg;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
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 < mpRedlineTbl->size() ; ++n )
|
|
{
|
|
const SwRangeRedline* pTmp = (*mpRedlineTbl)[ 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;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
bool SwExtraRedlineTbl::DeleteAllTableRedlines( SwDoc* pDoc, const SwTable& rTable, bool bSaveInUndo, sal_uInt16 nRedlineTypeToDelete )
|
|
{
|
|
if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & pDoc->GetRedlineMode() )
|
|
return false;
|
|
|
|
bool bChg = false;
|
|
|
|
if (bSaveInUndo && pDoc->GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
// To-Do - Add 'Undo' support for deleting 'Table Cell' redlines
|
|
/*
|
|
SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange );
|
|
if( pUndo->GetRedlSaveCount() )
|
|
{
|
|
GetIDocumentUndoRedo().AppendUndo(pUndo);
|
|
}
|
|
else
|
|
delete pUndo;
|
|
*/
|
|
}
|
|
|
|
for(sal_uInt16 nCurRedlinePos = 0; nCurRedlinePos < GetSize(); ++nCurRedlinePos )
|
|
{
|
|
SwExtraRedline* pExtraRedline = GetRedline(nCurRedlinePos);
|
|
const SwTableCellRedline* pTableCellRedline = dynamic_cast<const SwTableCellRedline*>(pExtraRedline);
|
|
if (pTableCellRedline)
|
|
{
|
|
const SwTableBox *pRedTabBox = &pTableCellRedline->GetTableBox();
|
|
const SwTable& pRedTable = pRedTabBox->GetSttNd()->FindTableNode()->GetTable();
|
|
if ( &pRedTable == &rTable )
|
|
{
|
|
// Redline for this table
|
|
const SwRedlineData& aRedlineData = pTableCellRedline->GetRedlineData();
|
|
sal_uInt16 nRedlineType = aRedlineData.GetType();
|
|
|
|
// Check if this redline object type should be deleted
|
|
if( USHRT_MAX != nRedlineTypeToDelete && nRedlineTypeToDelete != nRedlineType )
|
|
continue;
|
|
|
|
DeleteAndDestroy( nCurRedlinePos );
|
|
bChg = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const SwTableRowRedline* pTableRowRedline = dynamic_cast<const SwTableRowRedline*>(pExtraRedline);
|
|
if (pTableRowRedline)
|
|
{
|
|
const SwTableLine *pRedTabLine = &pTableRowRedline->GetTableLine();
|
|
const SwTableBoxes &pRedTabBoxes = pRedTabLine->GetTabBoxes();
|
|
const SwTable& pRedTable = pRedTabBoxes[0]->GetSttNd()->FindTableNode()->GetTable();
|
|
if ( &pRedTable == &rTable )
|
|
{
|
|
// Redline for this table
|
|
const SwRedlineData& aRedlineData = pTableRowRedline->GetRedlineData();
|
|
sal_uInt16 nRedlineType = aRedlineData.GetType();
|
|
|
|
// Check if this redline object type should be deleted
|
|
if( USHRT_MAX != nRedlineTypeToDelete && nRedlineTypeToDelete != nRedlineType )
|
|
continue;
|
|
|
|
DeleteAndDestroy( nCurRedlinePos );
|
|
bChg = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bChg )
|
|
pDoc->SetModified();
|
|
|
|
return bChg;
|
|
}
|
|
|
|
bool SwExtraRedlineTbl::DeleteTableRowRedline( SwDoc* pDoc, const SwTableLine& rTableLine, bool bSaveInUndo, sal_uInt16 nRedlineTypeToDelete )
|
|
{
|
|
if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & pDoc->GetRedlineMode() )
|
|
return false;
|
|
|
|
bool bChg = false;
|
|
|
|
if (bSaveInUndo && pDoc->GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
// To-Do - Add 'Undo' support for deleting 'Table Cell' redlines
|
|
/*
|
|
SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange );
|
|
if( pUndo->GetRedlSaveCount() )
|
|
{
|
|
GetIDocumentUndoRedo().AppendUndo(pUndo);
|
|
}
|
|
else
|
|
delete pUndo;
|
|
*/
|
|
}
|
|
|
|
for(sal_uInt16 nCurRedlinePos = 0; nCurRedlinePos < GetSize(); ++nCurRedlinePos )
|
|
{
|
|
SwExtraRedline* pExtraRedline = GetRedline(nCurRedlinePos);
|
|
const SwTableRowRedline* pTableRowRedline = dynamic_cast<const SwTableRowRedline*>(pExtraRedline);
|
|
const SwTableLine *pRedTabLine = pTableRowRedline ? &pTableRowRedline->GetTableLine() : NULL;
|
|
if ( pRedTabLine == &rTableLine )
|
|
{
|
|
// Redline for this table row
|
|
const SwRedlineData& aRedlineData = pTableRowRedline->GetRedlineData();
|
|
sal_uInt16 nRedlineType = aRedlineData.GetType();
|
|
|
|
// Check if this redline object type should be deleted
|
|
if( USHRT_MAX != nRedlineTypeToDelete && nRedlineTypeToDelete != nRedlineType )
|
|
continue;
|
|
|
|
DeleteAndDestroy( nCurRedlinePos );
|
|
bChg = true;
|
|
}
|
|
}
|
|
|
|
if( bChg )
|
|
pDoc->SetModified();
|
|
|
|
return bChg;
|
|
}
|
|
|
|
bool SwExtraRedlineTbl::DeleteTableCellRedline( SwDoc* pDoc, const SwTableBox& rTableBox, bool bSaveInUndo, sal_uInt16 nRedlineTypeToDelete )
|
|
{
|
|
if( nsRedlineMode_t::REDLINE_IGNOREDELETE_REDLINES & pDoc->GetRedlineMode() )
|
|
return false;
|
|
|
|
bool bChg = false;
|
|
|
|
if (bSaveInUndo && pDoc->GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
// To-Do - Add 'Undo' support for deleting 'Table Cell' redlines
|
|
/*
|
|
SwUndoRedline* pUndo = new SwUndoRedline( UNDO_REDLINE, rRange );
|
|
if( pUndo->GetRedlSaveCount() )
|
|
{
|
|
GetIDocumentUndoRedo().AppendUndo(pUndo);
|
|
}
|
|
else
|
|
delete pUndo;
|
|
*/
|
|
}
|
|
|
|
for(sal_uInt16 nCurRedlinePos = 0; nCurRedlinePos < GetSize(); ++nCurRedlinePos )
|
|
{
|
|
SwExtraRedline* pExtraRedline = GetRedline(nCurRedlinePos);
|
|
const SwTableCellRedline* pTableCellRedline = dynamic_cast<const SwTableCellRedline*>(pExtraRedline);
|
|
const SwTableBox *pRedTabBox = pTableCellRedline ? &pTableCellRedline->GetTableBox() : NULL;
|
|
if ( pRedTabBox == &rTableBox )
|
|
{
|
|
// Redline for this table cell
|
|
const SwRedlineData& aRedlineData = pTableCellRedline->GetRedlineData();
|
|
sal_uInt16 nRedlineType = aRedlineData.GetType();
|
|
|
|
// Check if this redline object type should be deleted
|
|
if( USHRT_MAX != nRedlineTypeToDelete && nRedlineTypeToDelete != nRedlineType )
|
|
continue;
|
|
|
|
DeleteAndDestroy( nCurRedlinePos );
|
|
bChg = true;
|
|
}
|
|
}
|
|
|
|
if( bChg )
|
|
pDoc->SetModified();
|
|
|
|
return bChg;
|
|
}
|
|
|
|
const SwRangeRedline* SwDoc::GetRedline( const SwPosition& rPos,
|
|
sal_uInt16* pFndPos ) const
|
|
{
|
|
sal_uInt16 nO = mpRedlineTbl->size(), nM, nU = 0;
|
|
if( nO > 0 )
|
|
{
|
|
nO--;
|
|
while( nU <= nO )
|
|
{
|
|
nM = nU + ( nO - nU ) / 2;
|
|
const SwRangeRedline* pRedl = (*mpRedlineTbl)[ 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 ) )
|
|
{
|
|
while( nM && rPos == *(*mpRedlineTbl)[ nM - 1 ]->End() &&
|
|
rPos == *(*mpRedlineTbl)[ nM - 1 ]->Start() )
|
|
{
|
|
--nM;
|
|
pRedl = (*mpRedlineTbl)[ nM ];
|
|
}
|
|
// if there are format and insert changes in the same position
|
|
// show insert change first.
|
|
// since the redlines are sorted by position, only check the redline
|
|
// before and after the current redline
|
|
if( nsRedlineType_t::REDLINE_FORMAT == pRedl->GetType() )
|
|
{
|
|
if( nM && rPos >= *(*mpRedlineTbl)[ nM - 1 ]->Start() &&
|
|
rPos <= *(*mpRedlineTbl)[ nM - 1 ]->End() &&
|
|
( nsRedlineType_t::REDLINE_INSERT == (*mpRedlineTbl)[ nM - 1 ]->GetType() ) )
|
|
{
|
|
--nM;
|
|
pRedl = (*mpRedlineTbl)[ nM ];
|
|
}
|
|
else if( ( nM + 1 ) <= nO && rPos >= *(*mpRedlineTbl)[ nM + 1 ]->Start() &&
|
|
rPos <= *(*mpRedlineTbl)[ nM + 1 ]->End() &&
|
|
( nsRedlineType_t::REDLINE_INSERT == (*mpRedlineTbl)[ nM + 1 ]->GetType() ) )
|
|
{
|
|
++nM;
|
|
pRedl = (*mpRedlineTbl)[ 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;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
typedef sal_Bool (*Fn_AcceptReject)( SwRedlineTbl& rArr, sal_uInt16& rPos,
|
|
sal_Bool bCallDelete,
|
|
const SwPosition* pSttRng,
|
|
const SwPosition* pEndRng);
|
|
|
|
static 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;
|
|
SwRangeRedline* 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:
|
|
{
|
|
bool bCheck = false, bReplace = false;
|
|
switch( eCmp )
|
|
{
|
|
case POS_INSIDE:
|
|
if( *pSttRng == *pRStt )
|
|
pRedl->SetStart( *pEndRng, pRStt );
|
|
else
|
|
{
|
|
if( *pEndRng != *pREnd )
|
|
{
|
|
// split up
|
|
SwRangeRedline* pNew = new SwRangeRedline( *pRedl );
|
|
pNew->SetStart( *pEndRng );
|
|
rArr.Insert( pNew ); ++rPos;
|
|
}
|
|
pRedl->SetEnd( *pSttRng, pREnd );
|
|
bCheck = true;
|
|
}
|
|
break;
|
|
|
|
case POS_OVERLAP_BEFORE:
|
|
pRedl->SetStart( *pEndRng, pRStt );
|
|
bReplace = true;
|
|
break;
|
|
|
|
case POS_OVERLAP_BEHIND:
|
|
pRedl->SetEnd( *pSttRng, pREnd );
|
|
bCheck = true;
|
|
break;
|
|
|
|
case POS_OUTSIDE:
|
|
case POS_EQUAL:
|
|
rArr.DeleteAndDestroy( rPos-- );
|
|
break;
|
|
|
|
default:
|
|
bRet = sal_False;
|
|
}
|
|
|
|
if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
|
|
{
|
|
// re-insert
|
|
rArr.Remove( pRedl );
|
|
rArr.Insert( pRedl );
|
|
}
|
|
}
|
|
break;
|
|
case nsRedlineType_t::REDLINE_DELETE:
|
|
{
|
|
SwDoc& rDoc = *pRedl->GetDoc();
|
|
const SwPosition *pDelStt = 0, *pDelEnd = 0;
|
|
bool bDelRedl = 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 = 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( true ).nContent.Assign( 0, 0 );
|
|
aPam.GetBound( 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;
|
|
}
|
|
|
|
static 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;
|
|
SwRangeRedline* 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;
|
|
bool bDelRedl = 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:
|
|
{
|
|
// delete the range again
|
|
rArr.Remove( rPos-- );
|
|
bDelRedl = 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( true ).nContent.Assign( 0, 0 );
|
|
aPam.GetBound( 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:
|
|
{
|
|
SwRangeRedline* pNew = 0;
|
|
bool bCheck = false, bReplace = false;
|
|
|
|
switch( eCmp )
|
|
{
|
|
case POS_INSIDE:
|
|
{
|
|
if( 1 < pRedl->GetStackCount() )
|
|
{
|
|
pNew = new SwRangeRedline( *pRedl );
|
|
pNew->PopData();
|
|
}
|
|
if( *pSttRng == *pRStt )
|
|
{
|
|
pRedl->SetStart( *pEndRng, pRStt );
|
|
bReplace = true;
|
|
if( pNew )
|
|
pNew->SetEnd( *pEndRng );
|
|
}
|
|
else
|
|
{
|
|
if( *pEndRng != *pREnd )
|
|
{
|
|
// split up
|
|
SwRangeRedline* pCpy = new SwRangeRedline( *pRedl );
|
|
pCpy->SetStart( *pEndRng );
|
|
rArr.Insert( pCpy ); ++rPos;
|
|
if( pNew )
|
|
pNew->SetEnd( *pEndRng );
|
|
}
|
|
|
|
pRedl->SetEnd( *pSttRng, pREnd );
|
|
bCheck = true;
|
|
if( pNew )
|
|
pNew->SetStart( *pSttRng );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case POS_OVERLAP_BEFORE:
|
|
if( 1 < pRedl->GetStackCount() )
|
|
{
|
|
pNew = new SwRangeRedline( *pRedl );
|
|
pNew->PopData();
|
|
}
|
|
pRedl->SetStart( *pEndRng, pRStt );
|
|
bReplace = true;
|
|
if( pNew )
|
|
pNew->SetEnd( *pEndRng );
|
|
break;
|
|
|
|
case POS_OVERLAP_BEHIND:
|
|
if( 1 < pRedl->GetStackCount() )
|
|
{
|
|
pNew = new SwRangeRedline( *pRedl );
|
|
pNew->PopData();
|
|
}
|
|
pRedl->SetEnd( *pSttRng, pREnd );
|
|
bCheck = true;
|
|
if( pNew )
|
|
pNew->SetStart( *pSttRng );
|
|
break;
|
|
|
|
case POS_OUTSIDE:
|
|
case POS_EQUAL:
|
|
if( !pRedl->PopData() )
|
|
// deleting the RedlineObject is enough
|
|
rArr.DeleteAndDestroy( rPos-- );
|
|
break;
|
|
|
|
default:
|
|
bRet = sal_False;
|
|
}
|
|
|
|
if( pNew )
|
|
{
|
|
rArr.Insert( pNew ); ++rPos;
|
|
}
|
|
|
|
if( bReplace || ( bCheck && !pRedl->HasValidRange() ))
|
|
{
|
|
// re-insert
|
|
rArr.Remove( 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;
|
|
}
|
|
|
|
static const SwRangeRedline* lcl_FindCurrRedline( const SwPosition& rSttPos,
|
|
sal_uInt16& rPos,
|
|
bool bNext = true )
|
|
{
|
|
const SwRangeRedline* pFnd = 0;
|
|
const SwRedlineTbl& rArr = rSttPos.nNode.GetNode().GetDoc()->GetRedlineTbl();
|
|
for( ; rPos < rArr.size() ; ++rPos )
|
|
{
|
|
const SwRangeRedline* 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;
|
|
}
|
|
|
|
static int lcl_AcceptRejectRedl( Fn_AcceptReject fn_AcceptReject,
|
|
SwRedlineTbl& rArr, sal_Bool bCallDelete,
|
|
const SwPaM& rPam)
|
|
{
|
|
sal_uInt16 n = 0;
|
|
int nCount = 0;
|
|
|
|
const SwPosition* pStt = rPam.Start(),
|
|
* pEnd = pStt == rPam.GetPoint() ? rPam.GetMark()
|
|
: rPam.GetPoint();
|
|
const SwRangeRedline* pFnd = lcl_FindCurrRedline( *pStt, n, true );
|
|
if( pFnd && // Is new a part of it?
|
|
( *pFnd->Start() != *pStt || *pFnd->End() > *pEnd ))
|
|
{
|
|
// Only revoke the partial selection
|
|
if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
|
|
nCount++;
|
|
++n;
|
|
}
|
|
|
|
for( ; n < rArr.size(); ++n )
|
|
{
|
|
SwRangeRedline* pTmp = rArr[ n ];
|
|
if( pTmp->HasMark() && pTmp->IsVisible() )
|
|
{
|
|
if( *pTmp->End() <= *pEnd )
|
|
{
|
|
if( (*fn_AcceptReject)( rArr, n, bCallDelete, 0, 0 ))
|
|
nCount++;
|
|
}
|
|
else
|
|
{
|
|
if( *pTmp->Start() < *pEnd )
|
|
{
|
|
// Only revoke the partial selection
|
|
if( (*fn_AcceptReject)( rArr, n, bCallDelete, pStt, pEnd ))
|
|
nCount++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return nCount;
|
|
}
|
|
|
|
static void lcl_AdjustRedlineRange( SwPaM& rPam )
|
|
{
|
|
// The Selection is only in the ContentSection. If there are Redlines
|
|
// to Non-ContentNodes before or after that, then the Selections
|
|
// expand to them.
|
|
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 SwRangeRedline* 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 SwRangeRedline* 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;
|
|
|
|
// Switch to visible in any case
|
|
if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
|
|
(nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) )
|
|
SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | meRedlineMode));
|
|
|
|
SwRangeRedline* pTmp = (*mpRedlineTbl)[ nPos ];
|
|
if( pTmp->HasMark() && pTmp->IsVisible() )
|
|
{
|
|
if (GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
SwRewriter aRewriter;
|
|
|
|
aRewriter.AddRule(UndoArg1, 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( *mpRedlineTbl, nPos, bCallDelete );
|
|
|
|
if( nSeqNo )
|
|
{
|
|
if( USHRT_MAX == nPos )
|
|
nPos = 0;
|
|
sal_uInt16 nFndPos = 2 == nLoopCnt
|
|
? mpRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
|
|
: mpRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
|
|
if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
|
|
USHRT_MAX != ( nFndPos =
|
|
mpRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
|
|
pTmp = (*mpRedlineTbl)[ nPos = nFndPos ];
|
|
else
|
|
nLoopCnt = 0;
|
|
}
|
|
else
|
|
nLoopCnt = 0;
|
|
|
|
} while( nLoopCnt );
|
|
|
|
if( bRet )
|
|
{
|
|
CompressRedlines();
|
|
SetModified();
|
|
}
|
|
|
|
if (GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
|
|
}
|
|
}
|
|
return bRet;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
bool SwDoc::AcceptRedline( const SwPaM& rPam, bool bCallDelete )
|
|
{
|
|
// Switch to visible in any case
|
|
if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
|
|
(nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) )
|
|
SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | meRedlineMode));
|
|
|
|
// The Selection is only in the ContentSection. If there are Redlines
|
|
// to Non-ContentNodes before or after that, then the Selections
|
|
// expand to them.
|
|
SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
|
|
lcl_AdjustRedlineRange( aPam );
|
|
|
|
if (GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
GetIDocumentUndoRedo().StartUndo( UNDO_ACCEPT_REDLINE, NULL );
|
|
GetIDocumentUndoRedo().AppendUndo( new SwUndoAcceptRedline( aPam ));
|
|
}
|
|
|
|
int nRet = lcl_AcceptRejectRedl( lcl_AcceptRedline, *mpRedlineTbl,
|
|
bCallDelete, aPam );
|
|
if( nRet > 0 )
|
|
{
|
|
CompressRedlines();
|
|
SetModified();
|
|
}
|
|
if (GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
OUString aTmpStr;
|
|
|
|
{
|
|
SwRewriter aRewriter;
|
|
aRewriter.AddRule(UndoArg1, OUString::number(nRet));
|
|
aTmpStr = aRewriter.Apply(OUString(SW_RES(STR_N_REDLINES)));
|
|
}
|
|
|
|
SwRewriter aRewriter;
|
|
aRewriter.AddRule(UndoArg1, aTmpStr);
|
|
|
|
GetIDocumentUndoRedo().EndUndo( UNDO_ACCEPT_REDLINE, &aRewriter );
|
|
}
|
|
return nRet != 0;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
bool SwDoc::RejectRedline( sal_uInt16 nPos, bool bCallDelete )
|
|
{
|
|
sal_Bool bRet = sal_False;
|
|
|
|
// Switch to visible in any case
|
|
if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
|
|
(nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) )
|
|
SetRedlineMode( (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | meRedlineMode));
|
|
|
|
SwRangeRedline* pTmp = (*mpRedlineTbl)[ nPos ];
|
|
if( pTmp->HasMark() && pTmp->IsVisible() )
|
|
{
|
|
if (GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
SwRewriter aRewriter;
|
|
|
|
aRewriter.AddRule(UndoArg1, 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( *mpRedlineTbl, nPos, bCallDelete );
|
|
|
|
if( nSeqNo )
|
|
{
|
|
if( USHRT_MAX == nPos )
|
|
nPos = 0;
|
|
sal_uInt16 nFndPos = 2 == nLoopCnt
|
|
? mpRedlineTbl->FindNextSeqNo( nSeqNo, nPos )
|
|
: mpRedlineTbl->FindPrevSeqNo( nSeqNo, nPos );
|
|
if( USHRT_MAX != nFndPos || ( 0 != ( --nLoopCnt ) &&
|
|
USHRT_MAX != ( nFndPos =
|
|
mpRedlineTbl->FindPrevSeqNo( nSeqNo, nPos ))) )
|
|
pTmp = (*mpRedlineTbl)[ nPos = nFndPos ];
|
|
else
|
|
nLoopCnt = 0;
|
|
}
|
|
else
|
|
nLoopCnt = 0;
|
|
|
|
} while( nLoopCnt );
|
|
|
|
if( bRet )
|
|
{
|
|
CompressRedlines();
|
|
SetModified();
|
|
}
|
|
|
|
if (GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
|
|
}
|
|
}
|
|
return bRet;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
bool SwDoc::RejectRedline( const SwPaM& rPam, bool bCallDelete )
|
|
{
|
|
// Switch to visible in any case
|
|
if( (nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE) !=
|
|
(nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode) )
|
|
SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE | meRedlineMode));
|
|
|
|
// The Selection is only in the ContentSection. If there are Redlines
|
|
// to Non-ContentNodes before or after that, then the Selections
|
|
// expand to them.
|
|
SwPaM aPam( *rPam.GetMark(), *rPam.GetPoint() );
|
|
lcl_AdjustRedlineRange( aPam );
|
|
|
|
if (GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
GetIDocumentUndoRedo().StartUndo( UNDO_REJECT_REDLINE, NULL );
|
|
GetIDocumentUndoRedo().AppendUndo( new SwUndoRejectRedline(aPam) );
|
|
}
|
|
|
|
int nRet = lcl_AcceptRejectRedl( lcl_RejectRedline, *mpRedlineTbl,
|
|
bCallDelete, aPam );
|
|
if( nRet > 0 )
|
|
{
|
|
CompressRedlines();
|
|
SetModified();
|
|
}
|
|
if (GetIDocumentUndoRedo().DoesUndo())
|
|
{
|
|
OUString aTmpStr;
|
|
|
|
{
|
|
SwRewriter aRewriter;
|
|
aRewriter.AddRule(UndoArg1, OUString::number(nRet));
|
|
aTmpStr = aRewriter.Apply(OUString(SW_RES(STR_N_REDLINES)));
|
|
}
|
|
|
|
SwRewriter aRewriter;
|
|
aRewriter.AddRule(UndoArg1, aTmpStr);
|
|
|
|
GetIDocumentUndoRedo().EndUndo( UNDO_REJECT_REDLINE, &aRewriter );
|
|
}
|
|
|
|
return nRet != 0;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
const SwRangeRedline* SwDoc::SelNextRedline( SwPaM& rPam ) const
|
|
{
|
|
rPam.DeleteMark();
|
|
rPam.SetMark();
|
|
|
|
SwPosition& rSttPos = *rPam.GetPoint();
|
|
SwPosition aSavePos( rSttPos );
|
|
bool bRestart;
|
|
|
|
// If the starting position points to the last valid ContentNode,
|
|
// we take the next Redline in any case.
|
|
sal_uInt16 n = 0;
|
|
const SwRangeRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, 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 = false;
|
|
|
|
for( ; !pFnd && n < mpRedlineTbl->size(); ++n )
|
|
{
|
|
pFnd = (*mpRedlineTbl)[ n ];
|
|
if( pFnd->HasMark() && pFnd->IsVisible() )
|
|
{
|
|
*rPam.GetMark() = *pFnd->Start();
|
|
rSttPos = *pFnd->End();
|
|
break;
|
|
}
|
|
else
|
|
pFnd = 0;
|
|
}
|
|
|
|
if( pFnd )
|
|
{
|
|
// Merge all of the same type and author that are
|
|
// consecutive into one Selection.
|
|
const SwPosition* pPrevEnd = pFnd->End();
|
|
while( ++n < mpRedlineTbl->size() )
|
|
{
|
|
const SwRangeRedline* pTmp = (*mpRedlineTbl)[ 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 SwRangeRedline* 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 < mpRedlineTbl->size() )
|
|
{
|
|
bRestart = true;
|
|
*rPam.GetPoint() = *pSaveFnd->End();
|
|
}
|
|
else
|
|
{
|
|
rPam.DeleteMark();
|
|
*rPam.GetPoint() = aSavePos;
|
|
}
|
|
pFnd = 0;
|
|
}
|
|
}
|
|
} while( bRestart );
|
|
|
|
return pFnd;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
const SwRangeRedline* SwDoc::SelPrevRedline( SwPaM& rPam ) const
|
|
{
|
|
rPam.DeleteMark();
|
|
rPam.SetMark();
|
|
|
|
SwPosition& rSttPos = *rPam.GetPoint();
|
|
SwPosition aSavePos( rSttPos );
|
|
bool bRestart;
|
|
|
|
// If the starting position points to the last valid ContentNode,
|
|
// we take the previous Redline in any case.
|
|
sal_uInt16 n = 0;
|
|
const SwRangeRedline* pFnd = lcl_FindCurrRedline( rSttPos, n, 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 = false;
|
|
|
|
while( !pFnd && 0 < n )
|
|
{
|
|
pFnd = (*mpRedlineTbl)[ --n ];
|
|
if( pFnd->HasMark() && pFnd->IsVisible() )
|
|
{
|
|
*rPam.GetMark() = *pFnd->End();
|
|
rSttPos = *pFnd->Start();
|
|
}
|
|
else
|
|
pFnd = 0;
|
|
}
|
|
|
|
if( pFnd )
|
|
{
|
|
// Merge all of the same type and author that are
|
|
// consecutive into one Selection.
|
|
const SwPosition* pNextStt = pFnd->Start();
|
|
while( 0 < n )
|
|
{
|
|
const SwRangeRedline* pTmp = (*mpRedlineTbl)[ --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 SwRangeRedline* 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 = true;
|
|
*rPam.GetPoint() = *pSaveFnd->Start();
|
|
}
|
|
else
|
|
{
|
|
rPam.DeleteMark();
|
|
*rPam.GetPoint() = aSavePos;
|
|
}
|
|
pFnd = 0;
|
|
}
|
|
}
|
|
} while( bRestart );
|
|
|
|
return pFnd;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
// Set comment at the Redline
|
|
bool SwDoc::SetRedlineComment( const SwPaM& rPaM, const OUString& rS )
|
|
{
|
|
bool bRet = false;
|
|
const SwPosition* pStt = rPaM.Start(),
|
|
* pEnd = pStt == rPaM.GetPoint() ? rPaM.GetMark()
|
|
: rPaM.GetPoint();
|
|
sal_uInt16 n = 0;
|
|
if( lcl_FindCurrRedline( *pStt, n, true ) )
|
|
{
|
|
for( ; n < mpRedlineTbl->size(); ++n )
|
|
{
|
|
bRet = true;
|
|
SwRangeRedline* pTmp = (*mpRedlineTbl)[ n ];
|
|
if( pStt != pEnd && *pTmp->Start() > *pEnd )
|
|
break;
|
|
|
|
pTmp->SetComment( rS );
|
|
if( *pTmp->End() >= *pEnd )
|
|
break;
|
|
}
|
|
}
|
|
if( bRet )
|
|
SetModified();
|
|
|
|
return bRet;
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
// Create a new author if necessary
|
|
sal_uInt16 SwDoc::GetRedlineAuthor()
|
|
{
|
|
return SW_MOD()->GetRedlineAuthor();
|
|
}
|
|
|
|
/// Insert new author into the Table for the Readers etc.
|
|
sal_uInt16 SwDoc::InsertRedlineAuthor( const OUString& rNew )
|
|
{
|
|
return SW_MOD()->InsertRedlineAuthor(rNew);
|
|
}
|
|
|
|
void SwDoc::UpdateRedlineAttr()
|
|
{
|
|
const SwRedlineTbl& rTbl = GetRedlineTbl();
|
|
for( sal_uInt16 n = 0; n < rTbl.size(); ++n )
|
|
{
|
|
SwRangeRedline* pRedl = rTbl[ n ];
|
|
if( pRedl->IsVisible() )
|
|
pRedl->InvalidateRange();
|
|
}
|
|
|
|
// To-Do - add 'SwExtraRedlineTbl' also ?
|
|
}
|
|
|
|
/// Set comment text for the Redline, which is inserted later on via
|
|
/// AppendRedline. Is used by Autoformat.
|
|
/// A null pointer resets the mode. The pointer is not copied, so it
|
|
/// needs to stay valid!
|
|
void SwDoc::SetAutoFmtRedlineComment( const OUString* pTxt, sal_uInt16 nSeqNo )
|
|
{
|
|
mbIsAutoFmtRedline = 0 != pTxt;
|
|
if( pTxt )
|
|
{
|
|
if( !mpAutoFmtRedlnComment )
|
|
mpAutoFmtRedlnComment = new OUString( *pTxt );
|
|
else
|
|
*mpAutoFmtRedlnComment = *pTxt;
|
|
}
|
|
else
|
|
delete mpAutoFmtRedlnComment, mpAutoFmtRedlnComment = 0;
|
|
|
|
mnAutoFmtRedlnCommentNo = nSeqNo;
|
|
}
|
|
|
|
void SwDoc::SetRedlinePassword(
|
|
/*[in]*/const uno::Sequence <sal_Int8>& rNewPassword)
|
|
{
|
|
maRedlinePasswd = rNewPassword;
|
|
SetModified();
|
|
}
|
|
|
|
bool SwRedlineTbl::Insert( SwRangeRedline* p, bool bIns )
|
|
{
|
|
bool bRet = false;
|
|
if( p->HasValidRange() )
|
|
{
|
|
bRet = insert( p ).second;
|
|
p->CallDisplayFunc();
|
|
}
|
|
else if( bIns )
|
|
bRet = InsertWithValidRanges( p );
|
|
else
|
|
{
|
|
OSL_ENSURE( !this, "Redline: wrong range" );
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
bool SwRedlineTbl::Insert( SwRangeRedline* p, sal_uInt16& rP, bool bIns )
|
|
{
|
|
bool bRet = false;
|
|
if( p->HasValidRange() )
|
|
{
|
|
std::pair<_SwRedlineTbl::const_iterator, bool> rv = insert( p );
|
|
rP = rv.first - begin();
|
|
bRet = rv.second;
|
|
p->CallDisplayFunc();
|
|
}
|
|
else if( bIns )
|
|
bRet = InsertWithValidRanges( p, &rP );
|
|
else
|
|
{
|
|
OSL_ENSURE( !this, "Redline: wrong range" );
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
bool SwRedlineTbl::InsertWithValidRanges( SwRangeRedline* p, sal_uInt16* pInsPos )
|
|
{
|
|
// Create valid "sub-ranges" from the Selection
|
|
bool bAnyIns = 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();
|
|
}
|
|
|
|
SwRangeRedline* pNew = 0;
|
|
sal_uInt16 nInsPos;
|
|
|
|
if( aNewStt < *pEnd )
|
|
do {
|
|
if( !pNew )
|
|
pNew = new SwRangeRedline( 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();
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
CheckPosition( pNew->GetPoint(), pNew->GetMark() );
|
|
#endif
|
|
|
|
if( *pNew->GetPoint() != *pNew->GetMark() &&
|
|
pNew->HasValidRange() &&
|
|
Insert( pNew, nInsPos ) )
|
|
{
|
|
pNew->CallDisplayFunc();
|
|
bAnyIns = 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;
|
|
}
|
|
|
|
bool CompareSwRedlineTbl::operator()(SwRangeRedline* const &lhs, SwRangeRedline* const &rhs) const
|
|
{
|
|
return *lhs < *rhs;
|
|
}
|
|
|
|
_SwRedlineTbl::~_SwRedlineTbl()
|
|
{
|
|
DeleteAndDestroyAll();
|
|
}
|
|
|
|
sal_uInt16 SwRedlineTbl::GetPos(const SwRangeRedline* p) const
|
|
{
|
|
const_iterator it = find(const_cast<SwRangeRedline* const>(p));
|
|
if( it == end() )
|
|
return USHRT_MAX;
|
|
return it - begin();
|
|
}
|
|
|
|
bool SwRedlineTbl::Remove( const SwRangeRedline* p )
|
|
{
|
|
sal_uInt16 nPos = GetPos(p);
|
|
if (nPos != USHRT_MAX)
|
|
Remove(nPos);
|
|
return nPos != USHRT_MAX;
|
|
}
|
|
|
|
void SwRedlineTbl::Remove( sal_uInt16 nP )
|
|
{
|
|
SwDoc* pDoc = 0;
|
|
if( !nP && 1 == size() )
|
|
pDoc = front()->GetDoc();
|
|
|
|
erase( begin() + nP );
|
|
|
|
SwViewShell* pSh;
|
|
if( pDoc && !pDoc->IsInDtor() &&
|
|
0 != ( pSh = pDoc->GetCurrentViewShell()) )
|
|
pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
|
|
}
|
|
|
|
void SwRedlineTbl::DeleteAndDestroyAll()
|
|
{
|
|
DeleteAndDestroy(0, size());
|
|
}
|
|
|
|
void SwRedlineTbl::DeleteAndDestroy( sal_uInt16 nP, sal_uInt16 nL )
|
|
{
|
|
SwDoc* pDoc = 0;
|
|
if( !nP && nL && nL == size() )
|
|
pDoc = front()->GetDoc();
|
|
|
|
for( const_iterator it = begin() + nP; it != begin() + nP + nL; ++it )
|
|
delete *it;
|
|
erase( begin() + nP, begin() + nP + nL );
|
|
|
|
SwViewShell* pSh;
|
|
if( pDoc && !pDoc->IsInDtor() &&
|
|
0 != ( pSh = pDoc->GetCurrentViewShell() ) )
|
|
pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
|
|
}
|
|
|
|
/// Find the next or preceding Redline with the same seq.no.
|
|
/// We can limit the search using look ahead.
|
|
/// 0 or USHRT_MAX searches the whole array.
|
|
sal_uInt16 SwRedlineTbl::FindNextOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const
|
|
{
|
|
return nSttPos + 1 < (sal_uInt16)size()
|
|
? FindNextSeqNo( operator[]( nSttPos )->GetSeqNo(), nSttPos+1, nLookahead )
|
|
: USHRT_MAX;
|
|
}
|
|
|
|
sal_uInt16 SwRedlineTbl::FindPrevOfSeqNo( sal_uInt16 nSttPos, sal_uInt16 nLookahead ) const
|
|
{
|
|
return nSttPos ? FindPrevSeqNo( operator[]( 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 < size() )
|
|
{
|
|
nEnd = size();
|
|
if( nLookahead && USHRT_MAX != nLookahead &&
|
|
static_cast<size_t>(nSttPos + nLookahead) < size() )
|
|
nEnd = nSttPos + nLookahead;
|
|
|
|
for( ; nSttPos < nEnd; ++nSttPos )
|
|
if( nSeqNo == operator[]( 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 < size() )
|
|
{
|
|
nEnd = 0;
|
|
if( nLookahead && USHRT_MAX != nLookahead && nSttPos > nLookahead )
|
|
nEnd = nSttPos - nLookahead;
|
|
|
|
++nSttPos;
|
|
while( nSttPos > nEnd )
|
|
if( nSeqNo == operator[]( --nSttPos )->GetSeqNo() )
|
|
{
|
|
nRet = nSttPos;
|
|
break;
|
|
}
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
SwRedlineExtraData::~SwRedlineExtraData()
|
|
{
|
|
}
|
|
|
|
void SwRedlineExtraData::Accept( SwPaM& ) const
|
|
{
|
|
}
|
|
|
|
void SwRedlineExtraData::Reject( SwPaM& ) const
|
|
{
|
|
}
|
|
|
|
bool SwRedlineExtraData::operator == ( const SwRedlineExtraData& ) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SwRedlineExtraData_FmtColl::SwRedlineExtraData_FmtColl( const OUString& 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();
|
|
|
|
// What about Undo? Is it turned off?
|
|
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().getLength());
|
|
|
|
if( pTNd->HasSwAttrSet() )
|
|
{
|
|
// Only set those that are not there anymore. Others
|
|
// could have changed, but we don't touch these.
|
|
SfxItemSet aTmp( *pSet );
|
|
aTmp.Differentiate( *pTNd->GetpSwAttrSet() );
|
|
pDoc->InsertItemSet( rPam, aTmp, 0 );
|
|
}
|
|
else
|
|
{
|
|
pDoc->InsertItemSet( rPam, *pSet, 0 );
|
|
}
|
|
}
|
|
rPam.DeleteMark();
|
|
}
|
|
}
|
|
|
|
bool 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( true )
|
|
{
|
|
aWhichIds.push_back( pItem->Which() );
|
|
if( aIter.IsAtEnd() )
|
|
break;
|
|
pItem = aIter.NextItem();
|
|
}
|
|
}
|
|
|
|
SwRedlineExtraData_Format::SwRedlineExtraData_Format(
|
|
const SwRedlineExtraData_Format& rCpy )
|
|
: SwRedlineExtraData()
|
|
{
|
|
aWhichIds.insert( aWhichIds.begin(), rCpy.aWhichIds.begin(), rCpy.aWhichIds.end() );
|
|
}
|
|
|
|
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)));
|
|
|
|
// Actually we need to reset the Attribute here!
|
|
std::vector<sal_uInt16>::const_iterator it;
|
|
for( it = aWhichIds.begin(); it != aWhichIds.end(); ++it )
|
|
{
|
|
pDoc->InsertPoolItem( rPam, *GetDfltAttr( *it ),
|
|
nsSetAttrMode::SETATTR_DONTEXPAND );
|
|
}
|
|
|
|
pDoc->SetRedlineMode_intern( eOld );
|
|
}
|
|
|
|
bool SwRedlineExtraData_Format::operator == ( const SwRedlineExtraData& rCmp ) const
|
|
{
|
|
bool nRet = true;
|
|
size_t nEnd = aWhichIds.size();
|
|
if( nEnd != ((SwRedlineExtraData_Format&)rCmp).aWhichIds.size() )
|
|
nRet = false;
|
|
else
|
|
for( size_t n = 0; n < nEnd; ++n )
|
|
if( ((SwRedlineExtraData_Format&)rCmp).aWhichIds[n] != aWhichIds[n])
|
|
{
|
|
nRet = false;
|
|
break;
|
|
}
|
|
return nRet;
|
|
}
|
|
|
|
SwRedlineExtraData_FormattingChanges::SwRedlineExtraData_FormattingChanges( const SfxItemSet* pItemSet )
|
|
: pSet(0)
|
|
{
|
|
if( pItemSet && pItemSet->Count() )
|
|
pSet = new SfxItemSet( *pItemSet );
|
|
}
|
|
|
|
SwRedlineExtraData_FormattingChanges::SwRedlineExtraData_FormattingChanges( const SwRedlineExtraData_FormattingChanges& rCpy )
|
|
: SwRedlineExtraData()
|
|
{
|
|
if( rCpy.pSet->Count() )
|
|
{
|
|
pSet = new SfxItemSet( *(rCpy.pSet) );
|
|
}
|
|
else
|
|
{
|
|
pSet = 0;
|
|
}
|
|
}
|
|
|
|
SwRedlineExtraData_FormattingChanges::~SwRedlineExtraData_FormattingChanges()
|
|
{
|
|
delete pSet;
|
|
}
|
|
|
|
SwRedlineExtraData* SwRedlineExtraData_FormattingChanges::CreateNew() const
|
|
{
|
|
return new SwRedlineExtraData_FormattingChanges( *this );
|
|
}
|
|
|
|
void SwRedlineExtraData_FormattingChanges::Reject( SwPaM& rPam ) const
|
|
{
|
|
rPam.GetDoc(); // This is here just to prevent build 'warning'
|
|
|
|
// ToDo: Add 'Reject' logic
|
|
}
|
|
|
|
bool SwRedlineExtraData_FormattingChanges::operator == ( const SwRedlineExtraData& rExtraData ) const
|
|
{
|
|
const SwRedlineExtraData_FormattingChanges& rCmp = (SwRedlineExtraData_FormattingChanges&)rExtraData;
|
|
|
|
if ( !pSet && !rCmp.pSet )
|
|
{
|
|
// Both SfxItemSet are null
|
|
return true;
|
|
}
|
|
else if ( pSet && rCmp.pSet && *pSet == *rCmp.pSet )
|
|
{
|
|
// Both SfxItemSet exist and are equal
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
SfxItemSet* SwRedlineExtraData_FormattingChanges::GetItemSet( ) const
|
|
{
|
|
return pSet;
|
|
}
|
|
|
|
SwRedlineData::SwRedlineData( RedlineType_t eT, sal_uInt16 nAut )
|
|
: pNext( 0 ), pExtraData( 0 ),
|
|
aStamp( DateTime::SYSTEM ),
|
|
eType( eT ), nAuthor( nAut ), nSeqNo( 0 )
|
|
{
|
|
aStamp.SetSec( 0 );
|
|
aStamp.SetNanoSec( 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 )
|
|
{
|
|
}
|
|
|
|
// For sw3io: We now own pNext!
|
|
SwRedlineData::SwRedlineData(RedlineType_t eT, sal_uInt16 nAut, const DateTime& rDT,
|
|
const OUString& 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 is copied. The Pointer's ownership is thus NOT transferred
|
|
/// to the Redline Object!
|
|
void SwRedlineData::SetExtraData( const SwRedlineExtraData* pData )
|
|
{
|
|
delete pExtraData;
|
|
|
|
// Check if there is data - and if so - delete it
|
|
if( pData )
|
|
pExtraData = pData->CreateNew();
|
|
else
|
|
pExtraData = 0;
|
|
}
|
|
|
|
OUString SwRedlineData::GetDescr() const
|
|
{
|
|
OUString aResult;
|
|
|
|
aResult += SW_RES(STR_REDLINE_INSERT + GetType());
|
|
|
|
return aResult;
|
|
}
|
|
|
|
SwRangeRedline::SwRangeRedline(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();
|
|
}
|
|
|
|
SwRangeRedline::SwRangeRedline( 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();
|
|
}
|
|
|
|
SwRangeRedline::SwRangeRedline( const SwRedlineData& rData, const SwPosition& rPos )
|
|
: SwPaM( rPos ),
|
|
pRedlineData( new SwRedlineData( rData )),
|
|
pCntntSect( 0 )
|
|
{
|
|
bDelLastPara = bIsLastParaDelete = sal_False;
|
|
bIsVisible = sal_True;
|
|
}
|
|
|
|
SwRangeRedline::SwRangeRedline( const SwRangeRedline& rCpy )
|
|
: SwPaM( *rCpy.GetMark(), *rCpy.GetPoint() ),
|
|
pRedlineData( new SwRedlineData( *rCpy.pRedlineData )),
|
|
pCntntSect( 0 )
|
|
{
|
|
bDelLastPara = bIsLastParaDelete = sal_False;
|
|
bIsVisible = sal_True;
|
|
if( !rCpy.HasMark() )
|
|
DeleteMark();
|
|
}
|
|
|
|
SwRangeRedline::~SwRangeRedline()
|
|
{
|
|
if( pCntntSect )
|
|
{
|
|
// delete the ContentSection
|
|
if( !GetDoc()->IsInDtor() )
|
|
GetDoc()->DeleteSection( &pCntntSect->GetNode() );
|
|
delete pCntntSect;
|
|
}
|
|
delete pRedlineData;
|
|
}
|
|
|
|
/// Do we have a valid Selection?
|
|
sal_Bool SwRangeRedline::HasValidRange() const
|
|
{
|
|
const SwNode* pPtNd = &GetPoint()->nNode.GetNode(),
|
|
* pMkNd = &GetMark()->nNode.GetNode();
|
|
if( pPtNd->StartOfSectionNode() == pMkNd->StartOfSectionNode() &&
|
|
!pPtNd->StartOfSectionNode()->IsTableNode() &&
|
|
// invalid if points on the end of content
|
|
// 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 SwRangeRedline::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 SwRangeRedline::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: // Content has been inserted
|
|
bIsVisible = sal_True;
|
|
MoveFromSection();
|
|
break;
|
|
|
|
case nsRedlineType_t::REDLINE_DELETE: // Content has been deleted
|
|
bIsVisible = sal_True;
|
|
MoveFromSection();
|
|
break;
|
|
|
|
case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied
|
|
case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified
|
|
InvalidateRange();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
pDoc->SetRedlineMode_intern( eOld );
|
|
}
|
|
}
|
|
|
|
void SwRangeRedline::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: // Content has been inserted
|
|
bIsVisible = sal_True;
|
|
if( 1 <= nLoop )
|
|
MoveFromSection();
|
|
break;
|
|
|
|
case nsRedlineType_t::REDLINE_DELETE: // Content has been deleted
|
|
bIsVisible = sal_False;
|
|
switch( nLoop )
|
|
{
|
|
case 0: MoveToSection(); break;
|
|
case 1: CopyToSection(); break;
|
|
case 2: DelCopyOfSection(); break;
|
|
}
|
|
break;
|
|
|
|
case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied
|
|
case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified
|
|
if( 1 <= nLoop )
|
|
InvalidateRange();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
pDoc->SetRedlineMode_intern( eOld );
|
|
}
|
|
|
|
void SwRangeRedline::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());
|
|
|
|
// Determine the Type, it's the first on Stack
|
|
for( pCur = pRedlineData; pCur->pNext; )
|
|
pCur = pCur->pNext;
|
|
|
|
switch( pCur->eType )
|
|
{
|
|
case nsRedlineType_t::REDLINE_INSERT: // Content has been inserted
|
|
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 eingefuegt
|
|
bIsVisible = sal_True;
|
|
if( 1 <= nLoop )
|
|
MoveFromSection();
|
|
break;
|
|
|
|
case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied
|
|
case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified
|
|
if( 1 <= nLoop )
|
|
InvalidateRange();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
pDoc->SetRedlineMode_intern( eOld );
|
|
}
|
|
|
|
void SwRangeRedline::InvalidateRange() // trigger the Layout
|
|
{
|
|
sal_uLong nSttNd = GetMark()->nNode.GetIndex(),
|
|
nEndNd = GetPoint()->nNode.GetIndex();
|
|
sal_Int32 nSttCnt = GetMark()->nContent.GetIndex();
|
|
sal_Int32 nEndCnt = GetPoint()->nContent.GetIndex();
|
|
|
|
if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
|
|
{
|
|
sal_uLong nTmp = nSttNd; nSttNd = nEndNd; nEndNd = nTmp;
|
|
sal_Int32 nTmp2 = nSttCnt; nSttCnt = nEndCnt; nEndCnt = nTmp2;
|
|
}
|
|
|
|
SwUpdateAttr aHt( 0, 0, RES_FMT_CHG );
|
|
SwNodes& rNds = GetDoc()->GetNodes();
|
|
for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
|
|
{
|
|
SwNode* pNd = rNds[n];
|
|
if( pNd->IsTxtNode() )
|
|
{
|
|
aHt.nStart = n == nSttNd ? nSttCnt : 0;
|
|
aHt.nEnd = (n == nEndNd)
|
|
? nEndCnt
|
|
: static_cast<SwTxtNode*>(pNd)->GetTxt().getLength();
|
|
((SwTxtNode*)pNd)->ModifyNotification( &aHt, &aHt );
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Calculates the start and end position of the intersection rTmp and
|
|
text node nNdIdx */
|
|
void SwRangeRedline::CalcStartEnd( sal_uLong nNdIdx, sal_Int32& rStart, sal_Int32& rEnd ) const
|
|
{
|
|
const SwPosition *pRStt = Start(), *pREnd = End();
|
|
if( pRStt->nNode < nNdIdx )
|
|
{
|
|
if( pREnd->nNode > nNdIdx )
|
|
{
|
|
rStart = 0; // Paragraph is completely enclosed
|
|
rEnd = COMPLETE_STRING;
|
|
}
|
|
else
|
|
{
|
|
OSL_ENSURE( pREnd->nNode == nNdIdx,
|
|
"SwRedlineItr::Seek: GetRedlinePos Error" );
|
|
rStart = 0; // Paragraph is overlapped in the beginning
|
|
rEnd = pREnd->nContent.GetIndex();
|
|
}
|
|
}
|
|
else if( pRStt->nNode == nNdIdx )
|
|
{
|
|
rStart = pRStt->nContent.GetIndex();
|
|
if( pREnd->nNode == nNdIdx )
|
|
rEnd = pREnd->nContent.GetIndex(); // Within the Paragraph
|
|
else
|
|
rEnd = COMPLETE_STRING; // Paragraph is overlapped in the end
|
|
}
|
|
else
|
|
{
|
|
rStart = COMPLETE_STRING;
|
|
rEnd = COMPLETE_STRING;
|
|
}
|
|
}
|
|
|
|
void SwRangeRedline::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 )
|
|
{
|
|
// In order to not move other Redlines' indices, we set them
|
|
// to the end (is exclusive)
|
|
const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
|
|
for( sal_uInt16 n = 0; n < rTbl.size(); ++n )
|
|
{
|
|
SwRangeRedline* pRedl = rTbl[ n ];
|
|
if( pRedl->GetBound(true) == *pStt )
|
|
pRedl->GetBound(true) = *pEnd;
|
|
if( pRedl->GetBound(false) == *pStt )
|
|
pRedl->GetBound(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 SwRangeRedline::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( true );
|
|
|
|
// 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
|
|
// 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 );
|
|
|
|
// Take over the style from the EndNode if needed
|
|
// We don't want this in Doc::Copy
|
|
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 SwRangeRedline::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 )
|
|
{
|
|
// In order to not move other Redlines' indices, we set them
|
|
// to the end (is exclusive)
|
|
const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
|
|
for( sal_uInt16 n = 0; n < rTbl.size(); ++n )
|
|
{
|
|
SwRangeRedline* pRedl = rTbl[ n ];
|
|
if( pRedl->GetBound(true) == *pStt )
|
|
pRedl->GetBound(true) = *pEnd;
|
|
if( pRedl->GetBound(false) == *pStt )
|
|
pRedl->GetBound(false) = *pEnd;
|
|
}
|
|
}
|
|
|
|
if( pCSttNd && pCEndNd )
|
|
{
|
|
// #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 )
|
|
{
|
|
// 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 );
|
|
OSL_ENSURE( n != USHRT_MAX, "How strange. We don't exist!" );
|
|
for( bool bBreak = false; !bBreak && n > 0; )
|
|
{
|
|
--n;
|
|
bBreak = true;
|
|
if( rTbl[ n ]->GetBound(true) == *aPam.GetPoint() )
|
|
{
|
|
rTbl[ n ]->GetBound(true) = *pEnd;
|
|
bBreak = false;
|
|
}
|
|
if( rTbl[ n ]->GetBound(false) == *aPam.GetPoint() )
|
|
{
|
|
rTbl[ n ]->GetBound(false) = *pEnd;
|
|
bBreak = false;
|
|
}
|
|
}
|
|
|
|
SwPosition aEnd( *pEnd );
|
|
*GetPoint() = *pEnd;
|
|
*GetMark() = *pEnd;
|
|
DeleteMark();
|
|
|
|
aPam.GetBound( true ).nContent.Assign( 0, 0 );
|
|
aPam.GetBound( false ).nContent.Assign( 0, 0 );
|
|
aPam.DeleteMark();
|
|
pDoc->DelFullPara( aPam );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDoc->DeleteRange( aPam );
|
|
}
|
|
|
|
if( pStt == GetPoint() )
|
|
Exchange();
|
|
|
|
DeleteMark();
|
|
}
|
|
}
|
|
|
|
void SwRangeRedline::MoveFromSection()
|
|
{
|
|
if( pCntntSect )
|
|
{
|
|
SwDoc* pDoc = GetDoc();
|
|
const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
|
|
std::vector<SwPosition*> aBeforeArr, aBehindArr;
|
|
sal_uInt16 nMyPos = rTbl.GetPos( this );
|
|
OSL_ENSURE( this, "this is not in the array?" );
|
|
bool bBreak = false;
|
|
sal_uInt16 n;
|
|
|
|
for( n = nMyPos+1; !bBreak && n < rTbl.size(); ++n )
|
|
{
|
|
bBreak = true;
|
|
if( rTbl[ n ]->GetBound(true) == *GetPoint() )
|
|
{
|
|
aBehindArr.push_back( &rTbl[ n ]->GetBound(true) );
|
|
bBreak = false;
|
|
}
|
|
if( rTbl[ n ]->GetBound(false) == *GetPoint() )
|
|
{
|
|
aBehindArr.push_back( &rTbl[ n ]->GetBound(false) );
|
|
bBreak = false;
|
|
}
|
|
}
|
|
for( bBreak = false, n = nMyPos; !bBreak && n ; )
|
|
{
|
|
--n;
|
|
bBreak = true;
|
|
if( rTbl[ n ]->GetBound(true) == *GetPoint() )
|
|
{
|
|
aBeforeArr.push_back( &rTbl[ n ]->GetBound(true) );
|
|
bBreak = false;
|
|
}
|
|
if( rTbl[ n ]->GetBound(false) == *GetPoint() )
|
|
{
|
|
aBeforeArr.push_back( &rTbl[ n ]->GetBound(false) );
|
|
bBreak = false;
|
|
}
|
|
}
|
|
|
|
const SwNode* pKeptCntntSectNode( &pCntntSect->GetNode() ); // #i95711#
|
|
{
|
|
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 );
|
|
const sal_Int32 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 );
|
|
}
|
|
// #i95771#
|
|
// Under certain conditions the previous <SwDoc::Move(..)> has already
|
|
// removed the change tracking section of this <SwRangeRedline> 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;
|
|
|
|
// adjustment of redline table positions must take start and
|
|
// end into account, not point and mark.
|
|
for( n = 0; n < aBeforeArr.size(); ++n )
|
|
*aBeforeArr[ n ] = *Start();
|
|
for( n = 0; n < aBehindArr.size(); ++n )
|
|
*aBehindArr[ n ] = *End();
|
|
}
|
|
else
|
|
InvalidateRange();
|
|
}
|
|
|
|
// for Undo
|
|
void SwRangeRedline::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;
|
|
}
|
|
else
|
|
{
|
|
OSL_FAIL("SwRangeRedline::SetContentIdx: invalid state");
|
|
}
|
|
}
|
|
|
|
sal_Bool SwRangeRedline::CanCombine( const SwRangeRedline& rRedl ) const
|
|
{
|
|
return IsVisible() && rRedl.IsVisible() &&
|
|
pRedlineData->CanCombine( *rRedl.pRedlineData );
|
|
}
|
|
|
|
void SwRangeRedline::PushData( const SwRangeRedline& rRedl, sal_Bool bOwnAsNext )
|
|
{
|
|
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 SwRangeRedline::PopData()
|
|
{
|
|
if( !pRedlineData->pNext )
|
|
return sal_False;
|
|
SwRedlineData* pCur = pRedlineData;
|
|
pRedlineData = pCur->pNext;
|
|
pCur->pNext = 0;
|
|
delete pCur;
|
|
return sal_True;
|
|
}
|
|
|
|
sal_uInt16 SwRangeRedline::GetStackCount() const
|
|
{
|
|
sal_uInt16 nRet = 1;
|
|
for( SwRedlineData* pCur = pRedlineData; pCur->pNext; ++nRet )
|
|
pCur = pCur->pNext;
|
|
return nRet;
|
|
}
|
|
|
|
sal_uInt16 SwRangeRedline::GetAuthor( sal_uInt16 nPos ) const
|
|
{
|
|
return GetRedlineData(nPos).nAuthor;
|
|
}
|
|
|
|
OUString SwRangeRedline::GetAuthorString( sal_uInt16 nPos ) const
|
|
{
|
|
return SW_MOD()->GetRedlineAuthor(GetRedlineData(nPos).nAuthor);
|
|
}
|
|
|
|
const DateTime& SwRangeRedline::GetTimeStamp( sal_uInt16 nPos ) const
|
|
{
|
|
return GetRedlineData(nPos).aStamp;
|
|
}
|
|
|
|
RedlineType_t SwRangeRedline::GetRealType( sal_uInt16 nPos ) const
|
|
{
|
|
return GetRedlineData(nPos).eType;
|
|
}
|
|
|
|
const OUString& SwRangeRedline::GetComment( sal_uInt16 nPos ) const
|
|
{
|
|
return GetRedlineData(nPos).sComment;
|
|
}
|
|
|
|
bool SwRangeRedline::operator==( const SwRangeRedline& rCmp ) const
|
|
{
|
|
return this == &rCmp;
|
|
}
|
|
|
|
bool SwRangeRedline::operator<( const SwRangeRedline& rCmp ) const
|
|
{
|
|
bool nResult = false;
|
|
|
|
if (*Start() < *rCmp.Start())
|
|
nResult = true;
|
|
else if (*Start() == *rCmp.Start())
|
|
if (*End() < *rCmp.End())
|
|
nResult = true;
|
|
|
|
return nResult;
|
|
}
|
|
|
|
const SwRedlineData & SwRangeRedline::GetRedlineData(sal_uInt16 nPos) const
|
|
{
|
|
SwRedlineData * pCur = pRedlineData;
|
|
|
|
while (nPos > 0 && NULL != pCur->pNext)
|
|
{
|
|
pCur = pCur->pNext;
|
|
|
|
nPos--;
|
|
}
|
|
|
|
OSL_ENSURE( 0 == nPos, "Pos is too big" );
|
|
|
|
return *pCur;
|
|
}
|
|
|
|
OUString SwRangeRedline::GetDescr(sal_uInt16 nPos)
|
|
{
|
|
OUString 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
|
|
OUString aTmpStr;
|
|
aTmpStr += SW_RES(STR_START_QUOTE);
|
|
aTmpStr += ShortenString(pPaM->GetTxt(), nUndoStringLength,
|
|
OUString(SW_RES(STR_LDOTS)));
|
|
aTmpStr += SW_RES(STR_END_QUOTE);
|
|
|
|
SwRewriter aRewriter;
|
|
aRewriter.AddRule(UndoArg1, aTmpStr);
|
|
|
|
aResult = aRewriter.Apply(aResult);
|
|
|
|
if (bDeletePaM)
|
|
delete pPaM;
|
|
|
|
return aResult;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
sal_uInt16 SwExtraRedlineTbl::GetPos(const SwExtraRedline* p) const
|
|
{
|
|
std::vector<SwExtraRedline*>::const_iterator it = std::find(m_aExtraRedlines.begin(), m_aExtraRedlines.end(), p);
|
|
if( it == m_aExtraRedlines.end() )
|
|
return USHRT_MAX;
|
|
return it - m_aExtraRedlines.begin();
|
|
}
|
|
|
|
bool SwExtraRedlineTbl::Insert( SwExtraRedline* p )
|
|
{
|
|
m_aExtraRedlines.push_back( p );
|
|
//p->CallDisplayFunc();
|
|
return true;
|
|
}
|
|
|
|
void SwExtraRedlineTbl::Remove( sal_uInt16 nPos )
|
|
{
|
|
/*
|
|
SwDoc* pDoc = 0;
|
|
if( !nP && 1 == size() )
|
|
pDoc = front()->GetDoc();
|
|
*/
|
|
|
|
m_aExtraRedlines.erase( m_aExtraRedlines.begin() + nPos );
|
|
|
|
/*
|
|
SwViewShell* pSh;
|
|
if( pDoc && !pDoc->IsInDtor() &&
|
|
0 != ( pSh = pDoc->GetCurrentViewShell()) )
|
|
pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
|
|
*/
|
|
}
|
|
|
|
void SwExtraRedlineTbl::DeleteAndDestroy( sal_uInt16 nPos, sal_uInt16 nLen )
|
|
{
|
|
/*
|
|
SwDoc* pDoc = 0;
|
|
if( !nP && nL && nL == size() )
|
|
pDoc = front()->GetDoc();
|
|
*/
|
|
|
|
for( std::vector<SwExtraRedline*>::iterator it = m_aExtraRedlines.begin() + nPos; it != m_aExtraRedlines.begin() + nPos + nLen; ++it )
|
|
delete *it;
|
|
|
|
m_aExtraRedlines.erase( m_aExtraRedlines.begin() + nPos, m_aExtraRedlines.begin() + nPos + nLen );
|
|
|
|
/*
|
|
SwViewShell* pSh;
|
|
if( pDoc && !pDoc->IsInDtor() &&
|
|
0 != ( pSh = pDoc->GetCurrentViewShell() ) )
|
|
pSh->InvalidateWindows( SwRect( 0, 0, LONG_MAX, LONG_MAX ) );
|
|
*/
|
|
}
|
|
|
|
void SwExtraRedlineTbl::DeleteAndDestroyAll()
|
|
{
|
|
DeleteAndDestroy(0, m_aExtraRedlines.size());
|
|
}
|
|
|
|
SwExtraRedline::~SwExtraRedline()
|
|
{
|
|
}
|
|
|
|
SwTableRowRedline::SwTableRowRedline(const SwRedlineData& rData, const SwTableLine& rTableLine)
|
|
: m_aRedlineData(rData)
|
|
, m_rTableLine(rTableLine)
|
|
{
|
|
}
|
|
|
|
SwTableRowRedline::~SwTableRowRedline()
|
|
{
|
|
}
|
|
|
|
bool SwDoc::AppendTableRowRedline( SwTableRowRedline* pNewRedl, bool bCallDelete )
|
|
{
|
|
(void)bCallDelete;
|
|
|
|
// TO-DO - equivelant for 'SwTableRowRedline'
|
|
bool bMerged = false;
|
|
/*
|
|
_CHECK_REDLINE( this )
|
|
*/
|
|
|
|
if (IsRedlineOn() && !IsShowOriginal(meRedlineMode))
|
|
{
|
|
// TO-DO - equivelant for 'SwTableRowRedline'
|
|
/*
|
|
pNewRedl->InvalidateRange();
|
|
*/
|
|
|
|
// Make equivelant of 'AppendRedline' checks inside here too
|
|
|
|
mpExtraRedlineTbl->Insert( pNewRedl );
|
|
}
|
|
else
|
|
{
|
|
// TO DO - equivelant for 'SwTableRowRedline'
|
|
/*
|
|
if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
|
|
{
|
|
RedlineMode_t eOld = meRedlineMode;
|
|
// Set to NONE, so that the Delete::Redo merges the Redline data correctly!
|
|
// The ShowMode needs to be retained!
|
|
meRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
|
|
DeleteAndJoin( *pNewRedl );
|
|
meRedlineMode = eOld;
|
|
}
|
|
delete pNewRedl, pNewRedl = 0;
|
|
*/
|
|
}
|
|
// TO-DO - equivelant for 'SwTableRowRedline'
|
|
/*
|
|
_CHECK_REDLINE( this )
|
|
*/
|
|
|
|
return ( 0 != pNewRedl ) || bMerged;
|
|
}
|
|
|
|
SwTableCellRedline::SwTableCellRedline(const SwRedlineData& rData, const SwTableBox& rTableBox)
|
|
: m_aRedlineData(rData)
|
|
, m_rTableBox(rTableBox)
|
|
{
|
|
}
|
|
|
|
SwTableCellRedline::~SwTableCellRedline()
|
|
{
|
|
}
|
|
|
|
bool SwDoc::AppendTableCellRedline( SwTableCellRedline* pNewRedl, bool bCallDelete )
|
|
{
|
|
(void)bCallDelete;
|
|
|
|
// TO-DO - equivelant for 'SwTableCellRedline'
|
|
bool bMerged = false;
|
|
/*
|
|
_CHECK_REDLINE( this )
|
|
*/
|
|
|
|
if (IsRedlineOn() && !IsShowOriginal(meRedlineMode))
|
|
{
|
|
// TO-DO - equivelant for 'SwTableCellRedline'
|
|
/*
|
|
pNewRedl->InvalidateRange();
|
|
*/
|
|
|
|
// Make equivelant of 'AppendRedline' checks inside here too
|
|
|
|
mpExtraRedlineTbl->Insert( pNewRedl );
|
|
}
|
|
else
|
|
{
|
|
// TO DO - equivelant for 'SwTableCellRedline'
|
|
/*
|
|
if( bCallDelete && nsRedlineType_t::REDLINE_DELETE == pNewRedl->GetType() )
|
|
{
|
|
RedlineMode_t eOld = meRedlineMode;
|
|
// Set to NONE, so that the Delete::Redo merges the Redline data correctly!
|
|
// The ShowMode needs to be retained!
|
|
meRedlineMode = (RedlineMode_t)(eOld & ~(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE));
|
|
DeleteAndJoin( *pNewRedl );
|
|
meRedlineMode = eOld;
|
|
}
|
|
delete pNewRedl, pNewRedl = 0;
|
|
*/
|
|
}
|
|
// TO-DO - equivelant for 'SwTableCellRedline'
|
|
/*
|
|
_CHECK_REDLINE( this )
|
|
*/
|
|
|
|
return ( 0 != pNewRedl ) || bMerged;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
|