merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / undo / unredln.cxx
blob944e239daf28c98d4976522e79a0f8bbbc06b04c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: unredln.cxx,v $
10 * $Revision: 1.14 $
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>
37 #include <doc.hxx>
38 #include <swundo.hxx> // fuer die UndoIds
39 #include <pam.hxx>
40 #include <ndtxt.hxx>
41 #include <undobj.hxx>
42 #include <rolbck.hxx>
43 #include <redline.hxx>
44 #include <docary.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 )
60 // Redline beachten
61 SwDoc& rDoc = *rRange.GetDoc();
62 if( rDoc.IsRedlineOn() )
64 switch( nUserId )
66 case UNDO_DELETE:
67 case UNDO_REPLACE:
68 pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_DELETE, rDoc.GetRedlineAuthor() );
69 break;
70 default:
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;
82 else
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()
96 delete pRedlData;
97 delete pRedlSaveData;
100 void SwUndoRedline::Undo( SwUndoIter& rIter )
102 SwDoc* pDoc = &rIter.GetDoc();
103 SetPaM( *rIter.pAktPam );
105 // RedlineMode setzen?
106 _Undo( rIter );
108 if( pRedlSaveData )
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;
142 _Redo( rIter );
144 SetPaM( *rIter.pAktPam, TRUE );
145 pDoc->SetRedlineMode_intern( eOld );
148 // default ist leer
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 );
160 /* \f */
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 )
174 bCanGroup = TRUE;
175 bIsDelim = !GetAppCharClass().isLetterNumeric( pTNd->GetTxt(),
176 nSttCntnt );
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 )
197 BOOL bRet = FALSE;
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 )
206 int bIsEnd = 0;
207 if( rNext.nSttCntnt == nEndCntnt )
208 bIsEnd = 1;
209 else if( rNext.nEndCntnt == nSttCntnt )
210 bIsEnd = -1;
212 if( bIsEnd &&
213 (( !pRedlSaveData && !rNext.pRedlSaveData ) ||
214 ( pRedlSaveData && rNext.pRedlSaveData &&
215 SwUndo::CanRedlineGroup( *pRedlSaveData,
216 *rNext.pRedlSaveData, 1 != bIsEnd )
219 if( 1 == bIsEnd )
220 nEndCntnt = rNext.nEndCntnt;
221 else
222 nSttCntnt = rNext.nSttCntnt;
223 bRet = TRUE;
226 return bRet;
229 /* \f */
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()
241 delete pOpt;
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" );
261 ++nFnd;
262 rDoc.GetRedlineTbl()[nFnd]->Show();
263 SetPaM( *rIter.pAktPam );
267 SwPaM aTmp( *rIter.pAktPam->GetMark() );
268 aTmp.SetMark();
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 );
282 SetPaM( rPam );
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;
304 /* \f */
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 );
336 /* \f */
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()
371 delete pRedlData;
372 delete pUnDel;
373 delete pUnDel2;
374 delete pRedlSaveData;
377 void SwUndoCompDoc::Undo( SwUndoIter& rIter )
379 SwPaM* pPam = rIter.pAktPam;
380 SwDoc* pDoc = pPam->GetDoc();
382 SetPaM( *pPam );
384 if( !bInsert )
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
401 // direction.
402 if( !nSttCntnt && !nEndCntnt )
403 pPam->Exchange();
405 BOOL bJoinTxt, bJoinPrev;
406 ::lcl_GetJoinFlags( *pPam, bJoinTxt, bJoinPrev );
408 pUnDel = new SwUndoDelete( *pPam, FALSE );
410 if( bJoinTxt )
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);
417 if (pTmp)
419 SwNode * pEnd = pDoc->GetNodes().DocumentSectionEndNode(pTmp);
421 if (pTmp != pEnd)
423 pPam->SetMark();
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 );
431 pPam->DeleteMark();
433 else
435 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
437 pDoc->DeleteRedline( *pPam, true, USHRT_MAX );
439 if( pRedlSaveData )
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;
454 if( bInsert )
456 SetPaM( *pPam );
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 );
475 else
477 // SwRedlineMode eOld = pDoc->GetRedlineMode();
478 // pDoc->SetRedlineMode_intern( ( eOld & ~REDLINE_IGNORE) | REDLINE_ON );
480 if( pUnDel2 )
482 pUnDel2->Undo( rIter );
483 delete pUnDel2, pUnDel2 = 0;
485 pUnDel->Undo( rIter );
486 delete pUnDel, pUnDel = 0;
488 SetPaM( *pPam );
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 );