1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unredln.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <unotools/charclass.hxx>
38 #include <swundo.hxx> // fuer die UndoIds
43 #include <redline.hxx>
45 #include <sortopt.hxx>
47 extern void lcl_JoinText( SwPaM
& rPam
, BOOL bJoinPrev
);
48 extern void lcl_GetJoinFlags( SwPaM
& rPam
, BOOL
& rJoinTxt
, BOOL
& rJoinPrev
);
50 //------------------------------------------------------------------
52 inline SwDoc
& SwUndoIter::GetDoc() const { return *pAktPam
->GetDoc(); }
55 SwUndoRedline::SwUndoRedline( SwUndoId nUsrId
, const SwPaM
& rRange
)
56 : SwUndo( UNDO_REDLINE
), SwUndRng( rRange
),
57 pRedlData( 0 ), pRedlSaveData( 0 ), nUserId( nUsrId
),
58 bHiddenRedlines( FALSE
)
61 SwDoc
& rDoc
= *rRange
.GetDoc();
62 if( rDoc
.IsRedlineOn() )
68 pRedlData
= new SwRedlineData( nsRedlineType_t::REDLINE_DELETE
, rDoc
.GetRedlineAuthor() );
73 SetRedlineMode( rDoc
.GetRedlineMode() );
76 ULONG nEndExtra
= rDoc
.GetNodes().GetEndOfExtras().GetIndex();
78 pRedlSaveData
= new SwRedlineSaveDatas
;
79 if( !FillSaveData( rRange
, *pRedlSaveData
, FALSE
,
80 UNDO_REJECT_REDLINE
!= nUserId
))
81 delete pRedlSaveData
, pRedlSaveData
= 0;
84 bHiddenRedlines
= HasHiddenRedlines( *pRedlSaveData
);
85 if( bHiddenRedlines
) // dann muessen die NodeIndizies
86 { // vom SwUndRng korrigiert werden
87 nEndExtra
-= rDoc
.GetNodes().GetEndOfExtras().GetIndex();
88 nSttNode
-= nEndExtra
;
89 nEndNode
-= nEndExtra
;
94 SwUndoRedline::~SwUndoRedline()
100 void SwUndoRedline::Undo( SwUndoIter
& rIter
)
102 SwDoc
* pDoc
= &rIter
.GetDoc();
103 SetPaM( *rIter
.pAktPam
);
105 // RedlineMode setzen?
110 ULONG nEndExtra
= pDoc
->GetNodes().GetEndOfExtras().GetIndex();
111 SetSaveData( *pDoc
, *pRedlSaveData
);
112 if( bHiddenRedlines
)
114 pRedlSaveData
->DeleteAndDestroy( 0, pRedlSaveData
->Count() );
116 nEndExtra
= pDoc
->GetNodes().GetEndOfExtras().GetIndex() - nEndExtra
;
117 nSttNode
+= nEndExtra
;
118 nEndNode
+= nEndExtra
;
120 SetPaM( *rIter
.pAktPam
, TRUE
);
125 void SwUndoRedline::Redo( SwUndoIter
& rIter
)
127 SwDoc
* pDoc
= &rIter
.GetDoc();
128 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
129 pDoc
->SetRedlineMode_intern((RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
131 SetPaM( *rIter
.pAktPam
);
132 if( pRedlSaveData
&& bHiddenRedlines
)
134 ULONG nEndExtra
= pDoc
->GetNodes().GetEndOfExtras().GetIndex();
135 FillSaveData( *rIter
.pAktPam
, *pRedlSaveData
, FALSE
,
136 UNDO_REJECT_REDLINE
!= nUserId
);
138 nEndExtra
-= pDoc
->GetNodes().GetEndOfExtras().GetIndex();
139 nSttNode
-= nEndExtra
;
140 nEndNode
-= nEndExtra
;
144 SetPaM( *rIter
.pAktPam
, TRUE
);
145 pDoc
->SetRedlineMode_intern( eOld
);
149 void SwUndoRedline::_Undo( SwUndoIter
& )
153 // default ist Redlines entfernen
154 void SwUndoRedline::_Redo( SwUndoIter
& rIter
)
156 rIter
.GetDoc().DeleteRedline( *rIter
.pAktPam
, true, USHRT_MAX
);
162 SwUndoRedlineDelete::SwUndoRedlineDelete( const SwPaM
& rRange
, SwUndoId nUsrId
)
163 : SwUndoRedline( nUsrId
= (nUsrId
? nUsrId
: UNDO_DELETE
), rRange
),
164 bCanGroup( FALSE
), bIsDelim( FALSE
), bIsBackspace( FALSE
)
166 const SwTxtNode
* pTNd
;
167 if( UNDO_DELETE
== nUserId
&&
168 nSttNode
== nEndNode
&& nSttCntnt
+ 1 == nEndCntnt
&&
169 0 != (pTNd
= rRange
.GetNode()->GetTxtNode()) )
171 sal_Unicode cCh
= pTNd
->GetTxt().GetChar( nSttCntnt
);
172 if( CH_TXTATR_BREAKWORD
!= cCh
&& CH_TXTATR_INWORD
!= cCh
)
175 bIsDelim
= !GetAppCharClass().isLetterNumeric( pTNd
->GetTxt(),
177 bIsBackspace
= nSttCntnt
== rRange
.GetPoint()->nContent
.GetIndex();
181 bCacheComment
= false;
184 void SwUndoRedlineDelete::_Undo( SwUndoIter
& rIter
)
186 rIter
.GetDoc().DeleteRedline( *rIter
.pAktPam
, true, USHRT_MAX
);
189 void SwUndoRedlineDelete::_Redo( SwUndoIter
& rIter
)
191 if( *rIter
.pAktPam
->GetPoint() != *rIter
.pAktPam
->GetMark() )
192 rIter
.GetDoc().AppendRedline( new SwRedline( *pRedlData
, *rIter
.pAktPam
), FALSE
);
195 BOOL
SwUndoRedlineDelete::CanGrouping( const SwUndoRedlineDelete
& rNext
)
198 if( UNDO_DELETE
== nUserId
&& nUserId
== rNext
.nUserId
&&
199 bCanGroup
== rNext
.bCanGroup
&&
200 bIsDelim
== rNext
.bIsDelim
&&
201 bIsBackspace
== rNext
.bIsBackspace
&&
202 nSttNode
== nEndNode
&&
203 rNext
.nSttNode
== nSttNode
&&
204 rNext
.nEndNode
== nEndNode
)
207 if( rNext
.nSttCntnt
== nEndCntnt
)
209 else if( rNext
.nEndCntnt
== nSttCntnt
)
213 (( !pRedlSaveData
&& !rNext
.pRedlSaveData
) ||
214 ( pRedlSaveData
&& rNext
.pRedlSaveData
&&
215 SwUndo::CanRedlineGroup( *pRedlSaveData
,
216 *rNext
.pRedlSaveData
, 1 != bIsEnd
)
220 nEndCntnt
= rNext
.nEndCntnt
;
222 nSttCntnt
= rNext
.nSttCntnt
;
231 SwUndoRedlineSort::SwUndoRedlineSort( const SwPaM
& rRange
,
232 const SwSortOptions
& rOpt
)
233 : SwUndoRedline( UNDO_SORT_TXT
, rRange
),
234 pOpt( new SwSortOptions( rOpt
) ),
235 nSaveEndNode( nEndNode
), nOffset( 0 ), nSaveEndCntnt( nEndCntnt
)
239 SwUndoRedlineSort::~SwUndoRedlineSort()
244 void SwUndoRedlineSort::_Undo( SwUndoIter
& rIter
)
246 // im rIter.pAktPam ist der sortiete Bereich,
247 // im aSaveRange steht der kopierte, sprich der originale.
248 SwDoc
& rDoc
= rIter
.GetDoc();
250 if( 0 == ( nsRedlineMode_t::REDLINE_SHOW_DELETE
& rDoc
.GetRedlineMode()) )
252 // die beiden Redline Objecte suchen und diese dann anzeigen lassen,
253 // damit die Nodes wieder uebereinstimmen!
254 // das Geloeschte ist versteckt, also suche das INSERT
255 // Redline Object. Dahinter steht das Geloeschte
256 USHORT nFnd
= rDoc
.GetRedlinePos(
257 *rDoc
.GetNodes()[ nSttNode
+ nOffset
+ 1 ],
258 nsRedlineType_t::REDLINE_INSERT
);
259 ASSERT( USHRT_MAX
!= nFnd
&& nFnd
+1 < rDoc
.GetRedlineTbl().Count(),
260 "kein Insert Object gefunden" );
262 rDoc
.GetRedlineTbl()[nFnd
]->Show();
263 SetPaM( *rIter
.pAktPam
);
267 SwPaM
aTmp( *rIter
.pAktPam
->GetMark() );
269 aTmp
.GetPoint()->nNode
= nSaveEndNode
;
270 aTmp
.GetPoint()->nContent
.Assign( aTmp
.GetCntntNode(), nSaveEndCntnt
);
271 rDoc
.DeleteRedline( aTmp
, true, USHRT_MAX
);
274 rDoc
.DelFullPara( *rIter
.pAktPam
);
275 SetPaM( *rIter
.pAktPam
);
278 void SwUndoRedlineSort::_Redo( SwUndoIter
& rIter
)
280 SwPaM
& rPam
= *rIter
.pAktPam
;
281 rIter
.GetDoc().SortText( rPam
, *pOpt
);
283 rPam
.GetPoint()->nNode
= nSaveEndNode
;
284 rPam
.GetPoint()->nContent
.Assign( rPam
.GetCntntNode(), nSaveEndCntnt
);
287 void SwUndoRedlineSort::Repeat( SwUndoIter
& rIter
)
289 rIter
.GetDoc().SortText( *rIter
.pAktPam
, *pOpt
);
292 void SwUndoRedlineSort::SetSaveRange( const SwPaM
& rRange
)
294 const SwPosition
& rPos
= *rRange
.End();
295 nSaveEndNode
= rPos
.nNode
.GetIndex();
296 nSaveEndCntnt
= rPos
.nContent
.GetIndex();
299 void SwUndoRedlineSort::SetOffset( const SwNodeIndex
& rIdx
)
301 nOffset
= rIdx
.GetIndex() - nSttNode
;
306 SwUndoAcceptRedline::SwUndoAcceptRedline( const SwPaM
& rRange
)
307 : SwUndoRedline( UNDO_ACCEPT_REDLINE
, rRange
)
311 void SwUndoAcceptRedline::_Redo( SwUndoIter
& rIter
)
313 rIter
.GetDoc().AcceptRedline( *rIter
.pAktPam
, false );
316 void SwUndoAcceptRedline::Repeat( SwUndoIter
& rIter
)
318 rIter
.GetDoc().AcceptRedline( *rIter
.pAktPam
, true );
321 SwUndoRejectRedline::SwUndoRejectRedline( const SwPaM
& rRange
)
322 : SwUndoRedline( UNDO_REJECT_REDLINE
, rRange
)
326 void SwUndoRejectRedline::_Redo( SwUndoIter
& rIter
)
328 rIter
.GetDoc().RejectRedline( *rIter
.pAktPam
, false );
331 void SwUndoRejectRedline::Repeat( SwUndoIter
& rIter
)
333 rIter
.GetDoc().RejectRedline( *rIter
.pAktPam
, true );
338 SwUndoCompDoc::SwUndoCompDoc( const SwPaM
& rRg
, BOOL bIns
)
339 : SwUndo( UNDO_COMPAREDOC
), SwUndRng( rRg
), pRedlData( 0 ),
340 pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ), bInsert( bIns
)
342 SwDoc
* pDoc
= (SwDoc
*)rRg
.GetDoc();
343 if( pDoc
->IsRedlineOn() )
345 RedlineType_t eTyp
= bInsert
? nsRedlineType_t::REDLINE_INSERT
: nsRedlineType_t::REDLINE_DELETE
;
346 pRedlData
= new SwRedlineData( eTyp
, pDoc
->GetRedlineAuthor() );
347 SetRedlineMode( pDoc
->GetRedlineMode() );
351 SwUndoCompDoc::SwUndoCompDoc( const SwRedline
& rRedl
)
352 : SwUndo( UNDO_COMPAREDOC
), SwUndRng( rRedl
), pRedlData( 0 ),
353 pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ),
354 // fuers MergeDoc wird aber der jeweils umgekehrte Zweig benoetigt!
355 bInsert( nsRedlineType_t::REDLINE_DELETE
== rRedl
.GetType() )
357 SwDoc
* pDoc
= (SwDoc
*)rRedl
.GetDoc();
358 if( pDoc
->IsRedlineOn() )
360 pRedlData
= new SwRedlineData( rRedl
.GetRedlineData() );
361 SetRedlineMode( pDoc
->GetRedlineMode() );
364 pRedlSaveData
= new SwRedlineSaveDatas
;
365 if( !FillSaveData( rRedl
, *pRedlSaveData
, FALSE
, TRUE
))
366 delete pRedlSaveData
, pRedlSaveData
= 0;
369 SwUndoCompDoc::~SwUndoCompDoc()
374 delete pRedlSaveData
;
377 void SwUndoCompDoc::Undo( SwUndoIter
& rIter
)
379 SwPaM
* pPam
= rIter
.pAktPam
;
380 SwDoc
* pDoc
= pPam
->GetDoc();
386 // die Redlines loeschen
387 RedlineMode_t eOld
= pDoc
->GetRedlineMode();
388 pDoc
->SetRedlineMode_intern((RedlineMode_t
)(( eOld
& ~nsRedlineMode_t::REDLINE_IGNORE
) | nsRedlineMode_t::REDLINE_ON
));
390 pDoc
->DeleteRedline( *pPam
, true, USHRT_MAX
);
392 pDoc
->SetRedlineMode_intern( eOld
);
394 //per definition Point is end (in SwUndRng!)
395 SwCntntNode
* pCSttNd
= pPam
->GetCntntNode( FALSE
);
396 SwCntntNode
* pCEndNd
= pPam
->GetCntntNode( TRUE
);
398 // if start- and end-content is zero, then the doc-compare moves
399 // complete nodes into the current doc. And then the selection
400 // must be from end to start, so the delete join into the right
402 if( !nSttCntnt
&& !nEndCntnt
)
405 BOOL bJoinTxt
, bJoinPrev
;
406 ::lcl_GetJoinFlags( *pPam
, bJoinTxt
, bJoinPrev
);
408 pUnDel
= new SwUndoDelete( *pPam
, FALSE
);
411 ::lcl_JoinText( *pPam
, bJoinPrev
);
413 if( pCSttNd
&& !pCEndNd
)
415 // #112139# Do not step behind the end of content.
416 SwNode
* pTmp
= pPam
->GetNode(TRUE
);
419 SwNode
* pEnd
= pDoc
->GetNodes().DocumentSectionEndNode(pTmp
);
424 pPam
->GetPoint()->nNode
++;
425 pPam
->GetBound( TRUE
).nContent
.Assign( 0, 0 );
426 pPam
->GetBound( FALSE
).nContent
.Assign( 0, 0 );
427 pUnDel2
= new SwUndoDelete( *pPam
, TRUE
);
435 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
437 pDoc
->DeleteRedline( *pPam
, true, USHRT_MAX
);
440 SetSaveData( *pDoc
, *pRedlSaveData
);
442 SetPaM( rIter
, TRUE
);
446 void SwUndoCompDoc::Redo( SwUndoIter
& rIter
)
448 // setze noch den Cursor auf den Redo-Bereich
449 SwPaM
* pPam
= rIter
.pAktPam
;
450 SwDoc
* pDoc
= pPam
->GetDoc();
452 rIter
.pLastUndoObj
= 0;
458 if( pRedlData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
460 SwRedline
* pTmp
= new SwRedline( *pRedlData
, *pPam
);
461 ((SwRedlineTbl
&)pDoc
->GetRedlineTbl()).Insert( pTmp
);
462 pTmp
->InvalidateRange();
465 SwRedlineMode eOld = pDoc->GetRedlineMode();
466 pDoc->SetRedlineMode_intern( eOld & ~REDLINE_IGNORE );
467 pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ));
468 pDoc->SetRedlineMode_intern( eOld );
471 else if( !( nsRedlineMode_t::REDLINE_IGNORE
& GetRedlineMode() ) &&
472 pDoc
->GetRedlineTbl().Count() )
473 pDoc
->SplitRedline( *pPam
);
477 // SwRedlineMode eOld = pDoc->GetRedlineMode();
478 // pDoc->SetRedlineMode_intern( ( eOld & ~REDLINE_IGNORE) | REDLINE_ON );
482 pUnDel2
->Undo( rIter
);
483 delete pUnDel2
, pUnDel2
= 0;
485 pUnDel
->Undo( rIter
);
486 delete pUnDel
, pUnDel
= 0;
490 SwRedline
* pTmp
= new SwRedline( *pRedlData
, *pPam
);
491 ((SwRedlineTbl
&)pDoc
->GetRedlineTbl()).Insert( pTmp
);
492 if (pTmp
) // #i19649#
493 pTmp
->InvalidateRange();
495 // pDoc->SetRedlineMode_intern( eOld );
498 SetPaM( rIter
, TRUE
);