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