merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / undo / unsect.cxx
blob76f8efa30611e58bc6e8a83c566f992bbf77e6c2
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: unsect.cxx,v $
10 * $Revision: 1.17 $
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 <svx/linkmgr.hxx>
36 #include <fmtcntnt.hxx>
37 #include <doc.hxx>
38 #include <docary.hxx>
39 #include <swundo.hxx> // fuer die UndoIds
40 #include <pam.hxx>
41 #include <ndtxt.hxx>
42 #include <undobj.hxx>
43 #include <section.hxx>
44 #include <rolbck.hxx>
45 #include <redline.hxx>
46 #include <doctxm.hxx>
47 #include <ftnidx.hxx>
48 #include <editsh.hxx>
49 /// OD 04.10.2002 #102894#
50 /// class Calc needed for calculation of the hidden condition of a section.
51 #include <calc.hxx>
54 inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
56 SfxItemSet* lcl_GetAttrSet( const SwSection& rSect )
58 // Attribute des Formate sichern (Spalten, Farbe, ... )
59 // Cntnt- und Protect- Items interessieren nicht (stehen schon in der
60 // Section), muessen also entfernen werden
61 SfxItemSet* pAttr = 0;
62 if( rSect.GetFmt() )
64 USHORT nCnt = 1;
65 if( rSect.IsProtect() )
66 ++nCnt;
68 if( nCnt < rSect.GetFmt()->GetAttrSet().Count() )
70 pAttr = new SfxItemSet( rSect.GetFmt()->GetAttrSet() );
71 pAttr->ClearItem( RES_PROTECT );
72 pAttr->ClearItem( RES_CNTNT );
73 if( !pAttr->Count() )
74 delete pAttr, pAttr = 0;
77 return pAttr;
80 SwUndoInsSection::SwUndoInsSection( const SwPaM& rPam, const SwSection& rNew,
81 const SfxItemSet* pSet )
82 : SwUndo( UNDO_INSSECTION ), SwUndRng( rPam ),
83 pHistory( 0 ), pRedlData( 0 ), pAttr( 0 ), nSectNodePos( 0 )
85 if( rNew.ISA( SwTOXBaseSection ))
87 const SwTOXBase& rBase = (SwTOXBaseSection&)rNew;
88 pSection = new SwTOXBaseSection( rBase );
90 else
91 pSection = new SwSection( rNew.GetType(), rNew.GetName() );
92 *pSection = rNew;
94 SwDoc& rDoc = *(SwDoc*)rPam.GetDoc();
95 if( rDoc.IsRedlineOn() )
97 pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT,
98 rDoc.GetRedlineAuthor() );
99 SetRedlineMode( rDoc.GetRedlineMode() );
102 bSplitAtStt = FALSE;
103 bSplitAtEnd = FALSE;
104 bUpdateFtn = FALSE;
106 if( pSet && pSet->Count() )
107 pAttr = new SfxItemSet( *pSet );
109 if( !rPam.HasMark() )
111 const SwCntntNode* pCNd = rPam.GetPoint()->nNode.GetNode().GetCntntNode();
112 if( pCNd && pCNd->HasSwAttrSet() && (
113 !rPam.GetPoint()->nContent.GetIndex() ||
114 rPam.GetPoint()->nContent.GetIndex() == pCNd->Len() ))
116 SfxItemSet aBrkSet( rDoc.GetAttrPool(), aBreakSetRange );
117 aBrkSet.Put( *pCNd->GetpSwAttrSet() );
118 if( aBrkSet.Count() )
120 pHistory = new SwHistory;
121 pHistory->CopyFmtAttr( aBrkSet, pCNd->GetIndex() );
128 SwUndoInsSection::~SwUndoInsSection()
130 delete pSection;
131 delete pRedlData;
132 delete pAttr;
134 if( pHistory )
135 delete pHistory;
140 void SwUndoInsSection::Undo( SwUndoIter& rUndoIter )
142 SwDoc& rDoc = rUndoIter.GetDoc();
144 RemoveIdxFromSection( rDoc, nSectNodePos );
146 SwSectionNode* pNd = rDoc.GetNodes()[ nSectNodePos ]->GetSectionNode();
147 ASSERT( pNd, "wo ist mein SectionNode?" );
149 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
150 rDoc.DeleteRedline( *pNd, true, USHRT_MAX );
152 // lag keine Selektion vor ??
153 SwNodeIndex aIdx( *pNd );
154 if( ( !nEndNode && STRING_MAXLEN == nEndCntnt ) ||
155 ( nSttNode == nEndNode && nSttCntnt == nEndCntnt ))
156 // loesche einfach alle Nodes
157 rDoc.GetNodes().Delete( aIdx, pNd->EndOfSectionIndex() -
158 aIdx.GetIndex() );
159 else
160 // einfach das Format loeschen, der Rest erfolgt automatisch
161 rDoc.DelSectionFmt( pNd->GetSection().GetFmt() );
163 // muessen wir noch zusammenfassen ?
164 if( bSplitAtStt )
165 Join( rDoc, nSttNode );
167 if( bSplitAtEnd )
168 Join( rDoc, nEndNode );
170 if ( pHistory )
172 pHistory->TmpRollback( &rDoc, 0, false );
175 if( bUpdateFtn )
176 rDoc.GetFtnIdxs().UpdateFtn( aIdx );
178 SetPaM( rUndoIter );
182 void SwUndoInsSection::Redo( SwUndoIter& rUndoIter )
184 SwDoc& rDoc = rUndoIter.GetDoc();
185 SetPaM( rUndoIter );
187 const SwTOXBaseSection* pUpdateTOX = 0;
188 if( pSection->ISA( SwTOXBaseSection ))
190 const SwTOXBase& rBase = *(SwTOXBaseSection*)pSection;
191 pUpdateTOX = rDoc.InsertTableOf( *rUndoIter.pAktPam->GetPoint(),
192 rBase, pAttr, TRUE );
194 else
196 rDoc.InsertSwSection( *rUndoIter.pAktPam, *pSection, pAttr, true );
199 if( pHistory )
200 pHistory->SetTmpEnd( pHistory->Count() );
202 SwSectionNode* pSectNd = rDoc.GetNodes()[ nSectNodePos ]->GetSectionNode();
203 if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
205 RedlineMode_t eOld = rDoc.GetRedlineMode();
206 rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
208 SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 );
209 rDoc.AppendRedline( new SwRedline( *pRedlData, aPam ), true);
210 rDoc.SetRedlineMode_intern( eOld );
212 else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
213 rDoc.GetRedlineTbl().Count() )
215 SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 );
216 rDoc.SplitRedline( aPam );
219 if( pUpdateTOX )
221 // Formatierung anstossen
222 SwEditShell* pESh = rDoc.GetEditShell();
223 if( pESh )
224 pESh->CalcLayout();
226 // Seitennummern eintragen
227 ((SwTOXBaseSection*)pUpdateTOX)->UpdatePageNum();
232 void SwUndoInsSection::Repeat( SwUndoIter& rUndoIter )
234 if( pSection->ISA( SwTOXBaseSection ))
236 const SwTOXBase& rBase = *(SwTOXBaseSection*)pSection;
237 rUndoIter.GetDoc().InsertTableOf( *rUndoIter.pAktPam->GetPoint(),
238 rBase, pAttr, TRUE );
240 else
242 rUndoIter.GetDoc().InsertSwSection( *rUndoIter.pAktPam,
243 *pSection, pAttr );
248 void SwUndoInsSection::Join( SwDoc& rDoc, ULONG nNode )
250 SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
251 SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
252 ASSERT( pTxtNd, "wo ist mein TextNode?" );
255 RemoveIdxRel( nNode + 1, SwPosition( aIdx,
256 SwIndex( pTxtNd, pTxtNd->GetTxt().Len() )));
258 pTxtNd->JoinNext();
260 if( pHistory )
262 SwIndex aCntIdx( pTxtNd, 0 );
263 pTxtNd->RstAttr( aCntIdx, pTxtNd->Len(), 0, 0, true );
268 void SwUndoInsSection::SaveSplitNode( SwTxtNode* pTxtNd, BOOL bAtStt )
270 if( pTxtNd->GetpSwpHints() )
272 if( !pHistory )
273 pHistory = new SwHistory;
274 pHistory->CopyAttr( pTxtNd->GetpSwpHints(), pTxtNd->GetIndex(), 0,
275 pTxtNd->GetTxt().Len(), false );
278 if( bAtStt )
279 bSplitAtStt = TRUE;
280 else
281 bSplitAtEnd = TRUE;
285 // -----------------------------
287 SwUndoDelSection::SwUndoDelSection( const SwSectionFmt& rFmt )
288 : SwUndo( UNDO_DELSECTION )
290 const SwSection& rSect = *rFmt.GetSection();
291 if( rSect.ISA( SwTOXBaseSection ))
293 const SwTOXBase& rBase = (SwTOXBaseSection&)rSect;
294 pSection = new SwTOXBaseSection( rBase );
296 else
297 pSection = new SwSection( rSect.GetType(), rSect.GetName() );
298 *pSection = rSect;
300 pAttr = ::lcl_GetAttrSet( rSect );
302 const SwNodeIndex* pIdx = rFmt.GetCntnt().GetCntntIdx();
303 nSttNd = pIdx->GetIndex();
304 nEndNd = pIdx->GetNode().EndOfSectionIndex();
308 SwUndoDelSection::~SwUndoDelSection()
310 delete pSection;
311 delete pAttr;
315 void SwUndoDelSection::Undo( SwUndoIter& rUndoIter )
317 SwDoc& rDoc = rUndoIter.GetDoc();
319 if( pSection->ISA( SwTOXBaseSection ))
321 const SwTOXBase& rBase = *(SwTOXBaseSection*)pSection;
322 rDoc.InsertTableOf( nSttNd, nEndNd-2, rBase, pAttr );
324 else
326 SwNodeIndex aStt( rDoc.GetNodes(), nSttNd );
327 SwNodeIndex aEnd( rDoc.GetNodes(), nEndNd-2 );
328 SwSectionFmt* pFmt = rDoc.MakeSectionFmt( 0 );
329 if( pAttr )
330 pFmt->SetFmtAttr( *pAttr );
332 /// OD 04.10.2002 #102894#
333 /// remember inserted section node for further calculations
334 SwSectionNode* pInsertedSectNd =
335 rDoc.GetNodes().InsertSection( aStt, *pFmt, *pSection, &aEnd );
337 if( SFX_ITEM_SET == pFmt->GetItemState( RES_FTN_AT_TXTEND ) ||
338 SFX_ITEM_SET == pFmt->GetItemState( RES_END_AT_TXTEND ))
340 rDoc.GetFtnIdxs().UpdateFtn( aStt );
343 /// OD 04.10.2002 #102894#
344 /// consider that section is hidden by condition.
345 /// If section is hidden by condition,
346 /// recalculate condition and update hidden condition flag.
347 /// Recalculation is necessary, because fields, on which the hide
348 /// condition depends, can be changed - fields changes aren't undoable.
349 /// NOTE: setting hidden condition flag also creates/deletes corresponding
350 /// frames, if the hidden condition flag changes.
351 SwSection& aInsertedSect = pInsertedSectNd->GetSection();
352 if ( aInsertedSect.IsHidden() &&
353 aInsertedSect.GetCondition().Len() > 0 )
355 SwCalc aCalc( rDoc );
356 rDoc.FldsToCalc(aCalc, pInsertedSectNd->GetIndex(), USHRT_MAX);
357 bool bRecalcCondHidden =
358 aCalc.Calculate( aInsertedSect.GetCondition() ).GetBool() ? true : false;
359 aInsertedSect.SetCondHidden( bRecalcCondHidden );
366 void SwUndoDelSection::Redo( SwUndoIter& rUndoIter )
368 SwDoc& rDoc = rUndoIter.GetDoc();
370 SwSectionNode* pNd = rDoc.GetNodes()[ nSttNd ]->GetSectionNode();
371 ASSERT( pNd, "wo ist mein SectionNode?" );
372 // einfach das Format loeschen, der Rest erfolgt automatisch
373 rDoc.DelSectionFmt( pNd->GetSection().GetFmt() );
378 SwUndoChgSection::SwUndoChgSection( const SwSectionFmt& rFmt, BOOL bOnlyAttr )
379 : SwUndo( UNDO_CHGSECTION ), bOnlyAttrChgd( bOnlyAttr )
381 const SwSection& rSect = *rFmt.GetSection();
382 pSection = new SwSection( rSect.GetType(), rSect.GetName() );
383 *pSection = rSect;
385 pAttr = ::lcl_GetAttrSet( rSect );
387 nSttNd = rFmt.GetCntnt().GetCntntIdx()->GetIndex();
391 SwUndoChgSection::~SwUndoChgSection()
393 delete pSection;
394 delete pAttr;
398 void SwUndoChgSection::Undo( SwUndoIter& rUndoIter )
400 SwDoc& rDoc = rUndoIter.GetDoc();
401 SwSectionNode* pSectNd = rDoc.GetNodes()[ nSttNd ]->GetSectionNode();
402 ASSERT( pSectNd, "wo ist mein SectionNode?" );
404 SwSection& rNdSect = pSectNd->GetSection();
405 SwFmt* pFmt = rNdSect.GetFmt();
407 SfxItemSet* pCur = ::lcl_GetAttrSet( rNdSect );
408 if( pAttr )
410 // das Content- und Protect-Item muss bestehen bleiben
411 const SfxPoolItem* pItem;
412 pAttr->Put( pFmt->GetFmtAttr( RES_CNTNT ));
413 if( SFX_ITEM_SET == pFmt->GetItemState( RES_PROTECT, TRUE, &pItem ))
414 pAttr->Put( *pItem );
415 pFmt->DelDiffs( *pAttr );
416 pAttr->ClearItem( RES_CNTNT );
417 pFmt->SetFmtAttr( *pAttr );
418 delete pAttr;
420 else
422 // dann muessen die alten entfernt werden
423 pFmt->ResetFmtAttr( RES_FRMATR_BEGIN, RES_BREAK );
424 pFmt->ResetFmtAttr( RES_HEADER, RES_OPAQUE );
425 pFmt->ResetFmtAttr( RES_SURROUND, RES_FRMATR_END-1 );
427 pAttr = pCur;
429 if( !bOnlyAttrChgd )
431 BOOL bUpdate = (!rNdSect.IsLinkType() && pSection->IsLinkType() ) ||
432 ( pSection->GetLinkFileName().Len() &&
433 pSection->GetLinkFileName() !=
434 rNdSect.GetLinkFileName());
436 SwSection* pTmp = new SwSection( CONTENT_SECTION, aEmptyStr );
437 *pTmp = rNdSect; // das aktuelle sichern
439 rNdSect = *pSection; // das alte setzen
441 delete pSection;
442 pSection = pTmp; // das aktuelle ist jetzt das alte
444 if( bUpdate )
445 rNdSect.CreateLink( CREATE_UPDATE );
446 else if( CONTENT_SECTION == rNdSect.GetType() && rNdSect.IsConnected() )
448 rNdSect.Disconnect();
449 rDoc.GetLinkManager().Remove( &rNdSect.GetBaseLink() );
455 void SwUndoChgSection::Redo( SwUndoIter& rUndoIter )
457 Undo( rUndoIter );