merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / undo / unattr.cxx
blob512c7c1afe39d2d9ffff8fd94e08f6d9f75bd8b3
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: unattr.cxx,v $
11 * $Revision: 1.21 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_sw.hxx"
36 #define _SVSTDARR_USHORTS
37 #define _SVSTDARR_USHORTSSORT
38 #include <hintids.hxx>
39 #include <svx/svdmodel.hxx>
40 #include <svx/tstpitem.hxx>
41 #include <svx/svdpage.hxx>
42 #include <svtools/itemiter.hxx>
45 #include <fmtflcnt.hxx>
46 #include <txtftn.hxx>
47 #include <fmtornt.hxx>
48 #include <fmtanchr.hxx>
49 #include <fmtfsize.hxx>
50 #include <frmfmt.hxx>
51 #include <fmtcntnt.hxx>
52 #include <ftnidx.hxx>
53 #include <doc.hxx>
54 #include <docary.hxx>
55 #include <swundo.hxx> // fuer die UndoIds
56 #include <pam.hxx>
57 #include <ndtxt.hxx>
58 #include <swtable.hxx>
59 #include <swtblfmt.hxx>
60 #include <undobj.hxx>
61 #include <rolbck.hxx>
62 #include <ndnotxt.hxx>
63 #include <dcontact.hxx>
64 #include <ftninfo.hxx>
65 #include <redline.hxx>
66 #include <section.hxx>
67 #include <charfmt.hxx>
71 inline SwDoc& SwUndoIter::GetDoc() const
72 { return *pAktPam->GetDoc(); }
74 // -----------------------------------------------------
76 SwUndoFmtAttrHelper::SwUndoFmtAttrHelper( SwFmt& rFmt, bool bSvDrwPt )
77 : SwClient( &rFmt )
78 , m_pUndo( 0 )
79 , m_bSaveDrawPt( bSvDrwPt )
83 void SwUndoFmtAttrHelper::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
85 if( pOld && pNew )
87 if( POOLATTR_END >= pOld->Which() )
89 if ( GetUndo() )
91 m_pUndo->PutAttr( *pOld );
93 else
95 m_pUndo.reset( new SwUndoFmtAttr( *pOld,
96 *static_cast<SwFmt*>(pRegisteredIn), m_bSaveDrawPt ) );
99 else if ( RES_ATTRSET_CHG == pOld->Which() )
101 if ( GetUndo() )
103 SfxItemIter aIter(
104 *(static_cast<SwAttrSetChg*>(pOld))->GetChgSet() );
105 const SfxPoolItem* pItem = aIter.GetCurItem();
106 while ( pItem )
108 m_pUndo->PutAttr( *pItem );
109 if( aIter.IsAtEnd() )
110 break;
111 pItem = aIter.NextItem();
114 else
116 m_pUndo.reset( new SwUndoFmtAttr(
117 *static_cast<SwAttrSetChg*>(pOld)->GetChgSet(),
118 *static_cast<SwFmt*>(pRegisteredIn), m_bSaveDrawPt ) );
121 else
122 SwClient::Modify( pOld, pNew );
124 else
125 SwClient::Modify( pOld, pNew );
128 // -----------------------------------------------------
130 SwUndoFmtAttr::SwUndoFmtAttr( const SfxItemSet& rOldSet,
131 SwFmt& rChgFmt,
132 bool bSaveDrawPt )
133 : SwUndo( UNDO_INSFMTATTR )
134 , m_pFmt( &rChgFmt )
135 // --> OD 2007-07-11 #i56253#
136 , m_pOldSet( new SfxItemSet( rOldSet ) )
137 // <--
138 , m_nNodeIndex( 0 )
139 , m_nFmtWhich( rChgFmt.Which() )
140 , m_bSaveDrawPt( bSaveDrawPt )
142 Init();
145 SwUndoFmtAttr::SwUndoFmtAttr( const SfxPoolItem& rItem, SwFmt& rChgFmt,
146 bool bSaveDrawPt )
147 : SwUndo( UNDO_INSFMTATTR )
148 , m_pFmt( &rChgFmt )
149 , m_pOldSet( m_pFmt->GetAttrSet().Clone( FALSE ) )
150 , m_nNodeIndex( 0 )
151 , m_nFmtWhich( rChgFmt.Which() )
152 , m_bSaveDrawPt( bSaveDrawPt )
154 m_pOldSet->Put( rItem );
155 Init();
158 void SwUndoFmtAttr::Init()
160 // treat change of anchor specially
161 if ( SFX_ITEM_SET == m_pOldSet->GetItemState( RES_ANCHOR, FALSE ))
163 SaveFlyAnchor( m_bSaveDrawPt );
165 else if ( RES_FRMFMT == m_nFmtWhich )
167 SwDoc* pDoc = m_pFmt->GetDoc();
168 if (USHRT_MAX != pDoc->GetTblFrmFmts()->GetPos(
169 static_cast<const SwFrmFmtPtr>(m_pFmt)))
171 // Table Format: save table position, table formats are volatile!
172 SwTable * pTbl = static_cast<SwTable*>(
173 SwClientIter( *m_pFmt ).First( TYPE( SwTable )) );
174 if ( pTbl )
176 m_nNodeIndex = pTbl->GetTabSortBoxes()[ 0 ]->GetSttNd()
177 ->FindTableNode()->GetIndex();
180 else if (USHRT_MAX != pDoc->GetSections().GetPos(
181 static_cast<const SwSectionFmtPtr>(m_pFmt)))
183 m_nNodeIndex = m_pFmt->GetCntnt().GetCntntIdx()->GetIndex();
185 else if ( 0 != dynamic_cast< SwTableBoxFmt* >( m_pFmt ) )
187 SwTableBox* pTblBox = static_cast< SwTableBox* >(
188 SwClientIter( *m_pFmt ).First( TYPE( SwTableBox )));
189 if ( pTblBox )
191 m_nNodeIndex = pTblBox->GetSttIdx();
197 SwUndoFmtAttr::~SwUndoFmtAttr()
201 void SwUndoFmtAttr::Undo( SwUndoIter& rUndoIter)
203 // OD 2004-10-26 #i35443#
204 // Important note: <Undo(..)> also called by <ReDo(..)>
206 if ( !m_pOldSet.get() || !m_pFmt || !IsFmtInDoc( &rUndoIter.GetDoc() ))
207 return;
209 // --> OD 2004-10-26 #i35443# - If anchor attribute has been successfull
210 // restored, all other attributes are also restored.
211 // Thus, keep track of its restoration
212 bool bAnchorAttrRestored( false );
213 if ( SFX_ITEM_SET == m_pOldSet->GetItemState( RES_ANCHOR, FALSE ))
215 bAnchorAttrRestored = RestoreFlyAnchor( rUndoIter );
216 if ( bAnchorAttrRestored )
218 // Anchor attribute successfull restored.
219 // Thus, keep anchor position for redo
220 SaveFlyAnchor();
222 else
224 // Anchor attribute not restored due to invalid anchor position.
225 // Thus, delete anchor attribute.
226 m_pOldSet->ClearItem( RES_ANCHOR );
230 if ( !bAnchorAttrRestored )
231 // <--
233 SwUndoFmtAttrHelper aTmp( *m_pFmt, m_bSaveDrawPt );
234 m_pFmt->SetFmtAttr( *m_pOldSet );
235 if ( aTmp.GetUndo() )
237 // transfer ownership of helper object's old set
238 m_pOldSet = aTmp.GetUndo()->m_pOldSet;
240 else
242 m_pOldSet->ClearItem();
245 if ( RES_FLYFRMFMT == m_nFmtWhich || RES_DRAWFRMFMT == m_nFmtWhich )
247 rUndoIter.pSelFmt = static_cast<SwFrmFmt*>(m_pFmt);
252 bool SwUndoFmtAttr::IsFmtInDoc( SwDoc* pDoc )
254 // search for the Format in the Document; if it does not exist any more,
255 // the attribute is not restored!
256 USHORT nPos = USHRT_MAX;
257 switch ( m_nFmtWhich )
259 case RES_TXTFMTCOLL:
260 nPos = pDoc->GetTxtFmtColls()->GetPos(
261 static_cast<const SwTxtFmtCollPtr>(m_pFmt) );
262 break;
264 case RES_GRFFMTCOLL:
265 nPos = pDoc->GetGrfFmtColls()->GetPos(
266 static_cast<const SwGrfFmtCollPtr>(m_pFmt) );
267 break;
269 case RES_CHRFMT:
270 nPos = pDoc->GetCharFmts()->GetPos(
271 static_cast<SwCharFmtPtr>(m_pFmt) );
272 break;
274 case RES_FRMFMT:
275 if ( m_nNodeIndex && (m_nNodeIndex < pDoc->GetNodes().Count()) )
277 SwNode* pNd = pDoc->GetNodes()[ m_nNodeIndex ];
278 if ( pNd->IsTableNode() )
280 m_pFmt =
281 static_cast<SwTableNode*>(pNd)->GetTable().GetFrmFmt();
282 nPos = 0;
283 break;
285 else if ( pNd->IsSectionNode() )
287 m_pFmt =
288 static_cast<SwSectionNode*>(pNd)->GetSection().GetFmt();
289 nPos = 0;
290 break;
292 else if ( pNd->IsStartNode() && (SwTableBoxStartNode ==
293 static_cast< SwStartNode* >(pNd)->GetStartNodeType()) )
295 SwTableNode* pTblNode = pNd->FindTableNode();
296 if ( pTblNode )
298 SwTableBox* pBox =
299 pTblNode->GetTable().GetTblBox( m_nNodeIndex );
300 if ( pBox )
302 m_pFmt = pBox->GetFrmFmt();
303 nPos = 0;
304 break;
309 // no break!
310 case RES_DRAWFRMFMT:
311 case RES_FLYFRMFMT:
312 nPos = pDoc->GetSpzFrmFmts()->GetPos(
313 static_cast<const SwFrmFmtPtr>(m_pFmt) );
314 if ( USHRT_MAX == nPos )
316 nPos = pDoc->GetFrmFmts()->GetPos(
317 static_cast<const SwFrmFmtPtr>(m_pFmt) );
319 break;
322 if ( USHRT_MAX == nPos )
324 // Format does not exist; reset
325 m_pFmt = 0;
328 return 0 != m_pFmt;
331 // prueft, ob es noch im Doc ist!
332 SwFmt* SwUndoFmtAttr::GetFmt( SwDoc& rDoc )
334 return m_pFmt && IsFmtInDoc( &rDoc ) ? m_pFmt : 0;
337 void SwUndoFmtAttr::Redo( SwUndoIter& rUndoIter)
339 // --> OD 2004-10-26 #i35443# - Because the undo stores the attributes for
340 // redo, the same code as for <Undo(..)> can be applied for <Redo(..)>
341 Undo( rUndoIter );
342 // <--
345 void SwUndoFmtAttr::Repeat( SwUndoIter& rUndoIter)
347 if ( !m_pOldSet.get() )
348 return;
350 if ( UNDO_INSFMTATTR == rUndoIter.GetLastUndoId())
352 SwUndoFmtAttr* pLast
353 = static_cast<SwUndoFmtAttr*>(rUndoIter.pLastUndoObj);
354 if (pLast->m_pOldSet.get() && pLast->m_pFmt)
356 return;
360 switch ( m_nFmtWhich )
362 case RES_GRFFMTCOLL:
364 SwNoTxtNode * pNd = rUndoIter.pAktPam->GetNode()->GetNoTxtNode();
365 if( pNd )
367 rUndoIter.GetDoc().SetAttr( m_pFmt->GetAttrSet(),
368 *pNd->GetFmtColl() );
371 break;
373 case RES_TXTFMTCOLL:
375 SwTxtNode * pNd = rUndoIter.pAktPam->GetNode()->GetTxtNode();
376 if( pNd )
378 rUndoIter.GetDoc().SetAttr( m_pFmt->GetAttrSet(),
379 *pNd->GetFmtColl() );
382 break;
384 // case RES_CHRFMT:
385 // case RES_FRMFMT:
387 case RES_FLYFRMFMT:
389 // erstal pruefen, ob der Cursor ueberhaupt in einem fliegenden
390 // Rahmen steht. Der Weg ist: suche in allen FlyFrmFormaten
391 // nach dem FlyCntnt-Attribut und teste ob der Cursor in der
392 // entsprechenden Section liegt.
393 SwFrmFmt* pFly = rUndoIter.pAktPam->GetNode()->GetFlyFmt();
394 if( pFly )
396 // Bug 43672: es duerfen nicht alle Attribute gesetzt werden!
397 if (SFX_ITEM_SET ==
398 m_pFmt->GetAttrSet().GetItemState( RES_CNTNT ))
400 SfxItemSet aTmpSet( m_pFmt->GetAttrSet() );
401 aTmpSet.ClearItem( RES_CNTNT );
402 if( aTmpSet.Count() )
403 rUndoIter.GetDoc().SetAttr( aTmpSet, *pFly );
405 else
407 rUndoIter.GetDoc().SetAttr( m_pFmt->GetAttrSet(), *pFly );
410 break;
414 rUndoIter.pLastUndoObj = this;
417 SwRewriter SwUndoFmtAttr::GetRewriter() const
419 SwRewriter aRewriter;
421 if (m_pFmt)
423 aRewriter.AddRule(UNDO_ARG1, m_pFmt->GetName());
426 return aRewriter;
429 void SwUndoFmtAttr::PutAttr( const SfxPoolItem& rItem )
431 m_pOldSet->Put( rItem );
432 if ( RES_ANCHOR == rItem.Which() )
434 SaveFlyAnchor( m_bSaveDrawPt );
438 void SwUndoFmtAttr::SaveFlyAnchor( bool bSvDrwPt )
440 // das Format ist gueltig, sonst wuerde man gar bis hier kommen
441 if( bSvDrwPt )
443 if ( RES_DRAWFRMFMT == m_pFmt->Which() )
445 Point aPt( static_cast<SwFrmFmt*>(m_pFmt)->FindSdrObject()
446 ->GetRelativePos() );
447 // store old value as attribute, to keep SwUndoFmtAttr small
448 m_pOldSet->Put( SwFmtFrmSize( ATT_VAR_SIZE, aPt.X(), aPt.Y() ) );
450 /* else
452 pOldSet->Put( pFmt->GetVertOrient() );
453 pOldSet->Put( pFmt->GetHoriOrient() );
455 */ }
457 const SwFmtAnchor& rAnchor =
458 static_cast<const SwFmtAnchor&>( m_pOldSet->Get( RES_ANCHOR, FALSE ) );
459 if( !rAnchor.GetCntntAnchor() )
460 return;
462 xub_StrLen nCntnt = 0;
463 switch( rAnchor.GetAnchorId() )
465 case FLY_IN_CNTNT:
466 case FLY_AUTO_CNTNT:
467 nCntnt = rAnchor.GetCntntAnchor()->nContent.GetIndex();
468 case FLY_AT_CNTNT:
469 case FLY_AT_FLY:
470 m_nNodeIndex = rAnchor.GetCntntAnchor()->nNode.GetIndex();
471 break;
472 default:
473 return;
476 SwFmtAnchor aAnchor( rAnchor.GetAnchorId(), nCntnt );
477 m_pOldSet->Put( aAnchor );
480 // --> OD 2004-10-26 #i35443# - Add return value, type <bool>.
481 // Return value indicates, if anchor attribute is restored.
482 // Note: If anchor attribute is restored, all other existing attributes
483 // are also restored.
484 bool SwUndoFmtAttr::RestoreFlyAnchor( SwUndoIter& rIter )
486 SwDoc* pDoc = &rIter.GetDoc();
487 SwFlyFrmFmt* pFrmFmt = static_cast<SwFlyFrmFmt*>(m_pFmt);
488 const SwFmtAnchor& rAnchor =
489 static_cast<const SwFmtAnchor&>( m_pOldSet->Get( RES_ANCHOR, FALSE ) );
491 SwFmtAnchor aNewAnchor( rAnchor.GetAnchorId() );
492 if( FLY_PAGE != rAnchor.GetAnchorId() )
494 SwNode* pNd = pDoc->GetNodes()[ m_nNodeIndex ];
496 if ( (FLY_AT_FLY == rAnchor.GetAnchorId())
497 ? ( !pNd->IsStartNode() || (SwFlyStartNode !=
498 static_cast<SwStartNode*>(pNd)->GetStartNodeType()) )
499 : !pNd->IsTxtNode() )
501 // --> OD 2004-10-26 #i35443# - invalid position.
502 // Thus, anchor attribute not restored
503 return false;
504 // <--
507 SwPosition aPos( *pNd );
508 if( FLY_IN_CNTNT == rAnchor.GetAnchorId() ||
509 FLY_AUTO_CNTNT == rAnchor.GetAnchorId() )
511 aPos.nContent.Assign( (SwTxtNode*)pNd, rAnchor.GetPageNum() );
512 if ( aPos.nContent.GetIndex() >
513 static_cast<SwTxtNode*>(pNd)->GetTxt().Len() )
515 // --> OD 2004-10-26 #i35443# - invalid position.
516 // Thus, anchor attribute not restored
517 return false;
518 // <--
521 aNewAnchor.SetAnchor( &aPos );
523 else
524 aNewAnchor.SetPageNum( rAnchor.GetPageNum() );
526 Point aDrawSavePt, aDrawOldPt;
527 if( pDoc->GetRootFrm() )
529 if( RES_DRAWFRMFMT == pFrmFmt->Which() )
531 // den alten zwischengespeicherten Wert herausholen.
532 const SwFmtFrmSize& rOldSize = static_cast<const SwFmtFrmSize&>(
533 m_pOldSet->Get( RES_FRM_SIZE ) );
534 aDrawSavePt.X() = rOldSize.GetWidth();
535 aDrawSavePt.Y() = rOldSize.GetHeight();
536 m_pOldSet->ClearItem( RES_FRM_SIZE );
538 // den akt. wieder zwischenspeichern
539 aDrawOldPt = pFrmFmt->FindSdrObject()->GetRelativePos();
540 //JP 08.10.97: ist laut AMA/MA nicht mehr noetig
541 // pCont->DisconnectFromLayout();
543 else
545 pFrmFmt->DelFrms(); // delete Frms
549 const SwFmtAnchor &rOldAnch = pFrmFmt->GetAnchor();
550 // --> OD 2006-03-13 #i54336#
551 // Consider case, that as-character anchored object has moved its anchor position.
552 if ( FLY_IN_CNTNT == rOldAnch.GetAnchorId() )
553 // <--
555 //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
556 //werden. Leider reisst dies neben den Frms auch noch das Format mit
557 //in sein Grab. Um dass zu unterbinden loesen wir vorher die
558 //Verbindung zwischen Attribut und Format.
559 const SwPosition *pPos = rOldAnch.GetCntntAnchor();
560 SwTxtNode *pTxtNode = (SwTxtNode*)&pPos->nNode.GetNode();
561 ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
562 const xub_StrLen nIdx = pPos->nContent.GetIndex();
563 SwTxtAttr * const pHnt =
564 pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
565 ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
566 "Missing FlyInCnt-Hint." );
567 ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt,
568 "Wrong TxtFlyCnt-Hint." );
569 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
571 //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
572 //werden.
573 pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
577 m_pOldSet->Put( aNewAnchor );
578 SwUndoFmtAttrHelper aTmp( *m_pFmt, m_bSaveDrawPt );
579 m_pFmt->SetFmtAttr( *m_pOldSet );
580 if ( aTmp.GetUndo() )
582 m_nNodeIndex = aTmp.GetUndo()->m_nNodeIndex;
583 // transfer ownership of helper object's old set
584 m_pOldSet = aTmp.GetUndo()->m_pOldSet;
586 else
588 m_pOldSet->ClearItem();
592 if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
594 SwDrawContact *pCont =
595 static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
596 // das Draw-Model hat auch noch ein Undo-Object fuer die
597 // richtige Position vorbereitet; dieses ist aber relativ.
598 // Darum verhinder hier, das durch setzen des Ankers das
599 // Contact-Object seine Position aendert.
600 //JP 08.10.97: ist laut AMA/MA nicht mehr noetig
601 // pCont->ConnectToLayout();
602 SdrObject* pObj = pCont->GetMaster();
604 if( pCont->GetAnchorFrm() && !pObj->IsInserted() )
606 ASSERT( pDoc->GetDrawModel(), "RestoreFlyAnchor without DrawModel" );
607 pDoc->GetDrawModel()->GetPage( 0 )->InsertObject( pObj );
609 pObj->SetRelativePos( aDrawSavePt );
611 // den alten Wert wieder zwischenspeichern.
612 m_pOldSet->Put(
613 SwFmtFrmSize( ATT_VAR_SIZE, aDrawOldPt.X(), aDrawOldPt.Y() ) );
616 if( FLY_IN_CNTNT == aNewAnchor.GetAnchorId() )
618 const SwPosition* pPos = aNewAnchor.GetCntntAnchor();
619 SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
620 ASSERT( pTxtNd, "no Text Node at position." );
621 SwFmtFlyCnt aFmt( pFrmFmt );
622 pTxtNd->InsertItem( aFmt, pPos->nContent.GetIndex(), 0 );
626 if( RES_DRAWFRMFMT != pFrmFmt->Which() )
627 pFrmFmt->MakeFrms();
629 rIter.pSelFmt = pFrmFmt;
631 // --> OD 2004-10-26 #i35443# - anchor attribute restored.
632 return true;
633 // <--
636 // -----------------------------------------------------
638 // --> OD 2008-02-12 #newlistlevelattrs#
639 SwUndoFmtResetAttr::SwUndoFmtResetAttr( SwFmt& rChangedFormat,
640 const USHORT nWhichId )
641 : SwUndo( UNDO_RESETATTR )
642 , m_pChangedFormat( &rChangedFormat )
643 , m_nWhichId( nWhichId )
644 , m_pOldItem( 0 )
646 const SfxPoolItem* pItem = 0;
647 if (rChangedFormat.GetItemState( nWhichId, FALSE, &pItem ) == SFX_ITEM_SET)
649 m_pOldItem.reset( pItem->Clone() );
653 SwUndoFmtResetAttr::~SwUndoFmtResetAttr()
657 void SwUndoFmtResetAttr::Undo( SwUndoIter& )
659 if ( m_pOldItem.get() )
661 m_pChangedFormat->SetFmtAttr( *m_pOldItem );
665 void SwUndoFmtResetAttr::Redo( SwUndoIter& )
667 if ( m_pOldItem.get() )
669 m_pChangedFormat->ResetFmtAttr( m_nWhichId );
672 // <--
674 // -----------------------------------------------------
676 SwUndoResetAttr::SwUndoResetAttr( const SwPaM& rRange, USHORT nFmtId )
677 : SwUndo( UNDO_RESETATTR ), SwUndRng( rRange )
678 , m_pHistory( new SwHistory )
679 , m_nFormatId( nFmtId )
683 SwUndoResetAttr::SwUndoResetAttr( const SwPosition& rPos, USHORT nFmtId )
684 : SwUndo( UNDO_RESETATTR )
685 , m_pHistory( new SwHistory )
686 , m_nFormatId( nFmtId )
688 nSttNode = nEndNode = rPos.nNode.GetIndex();
689 nSttCntnt = nEndCntnt = rPos.nContent.GetIndex();
692 SwUndoResetAttr::~SwUndoResetAttr()
696 void SwUndoResetAttr::Undo( SwUndoIter& rUndoIter )
698 // reset old values
699 SwDoc& rDoc = rUndoIter.GetDoc();
700 m_pHistory->TmpRollback( &rDoc, 0 );
701 m_pHistory->SetTmpEnd( m_pHistory->Count() );
703 if ((RES_CONDTXTFMTCOLL == m_nFormatId) &&
704 (nSttNode == nEndNode) && (nSttCntnt == nEndCntnt))
706 SwTxtNode* pTNd = rDoc.GetNodes()[ nSttNode ]->GetTxtNode();
707 if( pTNd )
709 SwIndex aIdx( pTNd, nSttCntnt );
710 pTNd->DontExpandFmt( aIdx, FALSE );
714 // setze noch den Cursor auf den Undo-Bereich
715 SetPaM( rUndoIter );
718 void SwUndoResetAttr::Redo( SwUndoIter& rUndoIter )
720 // setze Attribut in dem Bereich:
721 SetPaM( rUndoIter );
722 SwDoc& rDoc = rUndoIter.GetDoc();
723 rUndoIter.pLastUndoObj = 0;
724 SvUShortsSort* pIdArr = m_Ids.Count() ? &m_Ids : 0;
726 switch ( m_nFormatId )
728 case RES_CHRFMT:
729 rUndoIter.GetDoc().RstTxtAttrs( *rUndoIter.pAktPam );
730 break;
731 case RES_TXTFMTCOLL:
732 rUndoIter.GetDoc().ResetAttrs( *rUndoIter.pAktPam, FALSE, pIdArr );
733 break;
734 case RES_CONDTXTFMTCOLL:
735 rUndoIter.GetDoc().ResetAttrs( *rUndoIter.pAktPam, TRUE, pIdArr );
737 break;
738 case RES_TXTATR_TOXMARK:
739 // special treatment for TOXMarks
741 SwTOXMarks aArr;
742 SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
743 SwPosition aPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(),
744 nSttCntnt ));
746 USHORT nCnt = rDoc.GetCurTOXMark( aPos, aArr );
747 if( nCnt )
749 if( 1 < nCnt )
751 // search for the right one
752 SwHistoryHint* pHHint = (GetHistory())[ 0 ];
753 if( pHHint && HSTRY_SETTOXMARKHNT == pHHint->Which() )
755 while( nCnt )
757 if ( static_cast<SwHistorySetTOXMark*>(pHHint)
758 ->IsEqual( *aArr[ --nCnt ] ) )
760 ++nCnt;
761 break;
765 else
766 nCnt = 0;
768 // gefunden, also loeschen
769 if( nCnt-- )
771 rDoc.DeleteTOXMark( aArr[ nCnt ] );
775 break;
777 rUndoIter.pLastUndoObj = 0;
780 void SwUndoResetAttr::Repeat( SwUndoIter& rUndoIter )
782 if ( (RES_FMT_BEGIN > m_nFormatId) ||
783 ( (UNDO_RESETATTR == rUndoIter.GetLastUndoId()) &&
784 (m_nFormatId == static_cast<SwUndoResetAttr*>(rUndoIter.pLastUndoObj)
785 ->m_nFormatId) ) )
787 return;
790 SvUShortsSort* pIdArr = m_Ids.Count() ? &m_Ids : 0;
791 switch ( m_nFormatId )
793 case RES_CHRFMT:
794 rUndoIter.GetDoc().RstTxtAttrs( *rUndoIter.pAktPam );
795 break;
796 case RES_TXTFMTCOLL:
797 rUndoIter.GetDoc().ResetAttrs( *rUndoIter.pAktPam, FALSE, pIdArr );
798 break;
799 case RES_CONDTXTFMTCOLL:
800 rUndoIter.GetDoc().ResetAttrs( *rUndoIter.pAktPam, TRUE, pIdArr );
801 break;
803 rUndoIter.pLastUndoObj = this;
807 void SwUndoResetAttr::SetAttrs( const SvUShortsSort& rArr )
809 if ( m_Ids.Count() )
811 m_Ids.Remove( 0, m_Ids.Count() );
813 m_Ids.Insert( &rArr );
816 // -----------------------------------------------------
819 SwUndoAttr::SwUndoAttr( const SwPaM& rRange, const SfxPoolItem& rAttr,
820 const SetAttrMode nFlags )
821 : SwUndo( UNDO_INSATTR ), SwUndRng( rRange )
822 , m_AttrSet( rRange.GetDoc()->GetAttrPool(), rAttr.Which(), rAttr.Which() )
823 , m_pHistory( new SwHistory )
824 , m_pRedlineData( 0 )
825 , m_pRedlineSaveData( 0 )
826 , m_nNodeIndex( ULONG_MAX )
827 , m_nInsertFlags( nFlags )
829 m_AttrSet.Put( rAttr );
832 SwUndoAttr::SwUndoAttr( const SwPaM& rRange, const SfxItemSet& rSet,
833 const SetAttrMode nFlags )
834 : SwUndo( UNDO_INSATTR ), SwUndRng( rRange )
835 , m_AttrSet( rSet )
836 , m_pHistory( new SwHistory )
837 , m_pRedlineData( 0 )
838 , m_pRedlineSaveData( 0 )
839 , m_nNodeIndex( ULONG_MAX )
840 , m_nInsertFlags( nFlags )
844 SwUndoAttr::~SwUndoAttr()
848 void SwUndoAttr::SaveRedlineData( const SwPaM& rPam, BOOL bIsCntnt )
850 SwDoc* pDoc = rPam.GetDoc();
851 if ( pDoc->IsRedlineOn() )
853 m_pRedlineData.reset( new SwRedlineData( bIsCntnt
854 ? nsRedlineType_t::REDLINE_INSERT
855 : nsRedlineType_t::REDLINE_FORMAT,
856 pDoc->GetRedlineAuthor() ) );
859 m_pRedlineSaveData.reset( new SwRedlineSaveDatas );
860 if ( !FillSaveDataForFmt( rPam, *m_pRedlineSaveData ))
862 m_pRedlineSaveData.reset(0);
865 SetRedlineMode( pDoc->GetRedlineMode() );
866 if ( bIsCntnt )
868 m_nNodeIndex = rPam.GetPoint()->nNode.GetIndex();
872 void SwUndoAttr::Undo( SwUndoIter& rUndoIter )
874 SwDoc* pDoc = &rUndoIter.GetDoc();
876 RemoveIdx( *pDoc );
878 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
880 SwPaM& rPam = *rUndoIter.pAktPam;
881 if ( ULONG_MAX != m_nNodeIndex )
883 rPam.DeleteMark();
884 rPam.GetPoint()->nNode = m_nNodeIndex;
885 rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), nSttCntnt );
886 rPam.SetMark();
887 rPam.GetPoint()->nContent++;
888 pDoc->DeleteRedline( rPam, false, USHRT_MAX );
890 else
892 // alle Format-Redlines entfernen, werden ggfs. neu gesetzt
893 SetPaM( rUndoIter );
894 pDoc->DeleteRedline( rPam, false, nsRedlineType_t::REDLINE_FORMAT );
895 if ( m_pRedlineSaveData.get() )
897 SetSaveData( *pDoc, *m_pRedlineSaveData );
902 const bool bToLast = (1 == m_AttrSet.Count())
903 && (RES_TXTATR_FIELD <= *m_AttrSet.GetRanges())
904 && (*m_AttrSet.GetRanges() <= RES_TXTATR_FTN);
906 // restore old values
907 m_pHistory->TmpRollback( pDoc, 0, !bToLast );
908 m_pHistory->SetTmpEnd( m_pHistory->Count() );
910 // set cursor onto Undo area
911 SetPaM( rUndoIter );
914 int lcl_HasEqualItems( const SfxItemSet& rSet1, const SfxItemSet& rSet2 )
916 int nRet = -1;
917 SfxItemIter aIter1( rSet1 ), aIter2( rSet2 );
918 const SfxPoolItem *pI1 = aIter1.FirstItem(), *pI2 = aIter2.FirstItem();
920 while( pI1 && pI2 )
922 if( pI1->Which() != pI2->Which() ||
923 aIter1.IsAtEnd() != aIter2.IsAtEnd() )
925 nRet = 0;
926 break;
928 if( aIter1.IsAtEnd() )
929 break;
930 pI1 = aIter1.NextItem();
931 pI2 = aIter2.NextItem();
933 return nRet;
936 void SwUndoAttr::Repeat( SwUndoIter& rUndoIter )
938 if ( UNDO_INSATTR == rUndoIter.GetLastUndoId() )
940 SwUndoAttr* pLast = static_cast<SwUndoAttr*>(rUndoIter.pLastUndoObj);
941 if ((pLast->m_AttrSet.Count() == m_AttrSet.Count()) &&
942 (pLast->m_nInsertFlags == m_nInsertFlags ) &&
943 lcl_HasEqualItems( m_AttrSet, pLast->m_AttrSet ))
945 return;
950 // RefMarks are not repeat capable
951 if ( SFX_ITEM_SET != m_AttrSet.GetItemState( RES_TXTATR_REFMARK, FALSE ) )
953 rUndoIter.GetDoc().InsertItemSet( *rUndoIter.pAktPam,
954 m_AttrSet, m_nInsertFlags );
956 else if ( 1 < m_AttrSet.Count() )
958 SfxItemSet aTmpSet( m_AttrSet );
959 aTmpSet.ClearItem( RES_TXTATR_REFMARK );
960 rUndoIter.GetDoc().InsertItemSet( *rUndoIter.pAktPam,
961 aTmpSet, m_nInsertFlags );
963 rUndoIter.pLastUndoObj = this;
966 void SwUndoAttr::Redo( SwUndoIter& rUndoIter )
968 // setze Attribut in dem Bereich:
969 SetPaM( rUndoIter );
970 SwPaM& rPam = *rUndoIter.pAktPam;
971 SwDoc& rDoc = rUndoIter.GetDoc();
973 if ( m_pRedlineData.get() &&
974 IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
976 RedlineMode_t eOld = rDoc.GetRedlineMode();
977 rDoc.SetRedlineMode_intern(static_cast<RedlineMode_t>(
978 eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
979 rDoc.InsertItemSet( rPam, m_AttrSet, m_nInsertFlags );
981 if ( ULONG_MAX != m_nNodeIndex )
983 rPam.SetMark();
984 if ( rPam.Move( fnMoveBackward ) )
986 rDoc.AppendRedline( new SwRedline( *m_pRedlineData, rPam ),
987 true);
989 rPam.DeleteMark();
991 else
993 rDoc.AppendRedline( new SwRedline( *m_pRedlineData, rPam ), true);
996 rDoc.SetRedlineMode_intern( eOld );
998 else
1000 rDoc.InsertItemSet( rPam, m_AttrSet, m_nInsertFlags );
1003 rUndoIter.pLastUndoObj = 0;
1007 void SwUndoAttr::RemoveIdx( SwDoc& rDoc )
1009 if ( SFX_ITEM_SET != m_AttrSet.GetItemState( RES_TXTATR_FTN, FALSE ))
1010 return ;
1012 SwHistoryHint* pHstHnt;
1013 SwNodes& rNds = rDoc.GetNodes();
1014 for ( USHORT n = 0; n < m_pHistory->Count(); ++n )
1016 xub_StrLen nCntnt = 0;
1017 ULONG nNode = 0;
1018 pHstHnt = (*m_pHistory)[ n ];
1019 switch ( pHstHnt->Which() )
1021 case HSTRY_RESETTXTHNT:
1023 SwHistoryResetTxt * pHistoryHint
1024 = static_cast<SwHistoryResetTxt*>(pHstHnt);
1025 if ( RES_TXTATR_FTN == pHistoryHint->GetWhich() )
1027 nNode = pHistoryHint->GetNode();
1028 nCntnt = pHistoryHint->GetCntnt();
1031 break;
1033 case HSTRY_RESETATTRSET:
1035 SwHistoryResetAttrSet * pHistoryHint
1036 = static_cast<SwHistoryResetAttrSet*>(pHstHnt);
1037 nCntnt = pHistoryHint->GetCntnt();
1038 if ( STRING_MAXLEN != nCntnt )
1040 const SvUShorts& rArr = pHistoryHint->GetArr();
1041 for ( USHORT i = rArr.Count(); i; )
1043 if ( RES_TXTATR_FTN == rArr[ --i ] )
1045 nNode = pHistoryHint->GetNode();
1046 break;
1051 break;
1053 default:
1054 break;
1057 if( nNode )
1059 SwTxtNode* pTxtNd = rNds[ nNode ]->GetTxtNode();
1060 if( pTxtNd )
1062 SwIndex aIdx( pTxtNd, nCntnt );
1063 SwTxtAttr * pTxtHt = pTxtNd->GetTxtAttr( aIdx, RES_TXTATR_FTN );
1064 if( pTxtHt )
1066 // ok, dann hole mal die Werte
1067 SwTxtFtn* pFtn = static_cast<SwTxtFtn*>(pTxtHt);
1068 RemoveIdxFromSection( rDoc, pFtn->GetStartNode()->GetIndex() );
1069 return ;
1076 // -----------------------------------------------------
1078 SwUndoDefaultAttr::SwUndoDefaultAttr( const SfxItemSet& rSet )
1079 : SwUndo( UNDO_SETDEFTATTR )
1080 , m_pOldSet( 0 )
1081 , m_pTabStop( 0 )
1083 const SfxPoolItem* pItem;
1084 if( SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_TABSTOP, FALSE, &pItem ) )
1086 // store separately, because it may change!
1087 m_pTabStop.reset( static_cast<SvxTabStopItem*>(pItem->Clone()) );
1088 if ( 1 != rSet.Count() ) // are there more attributes?
1090 m_pOldSet.reset( new SfxItemSet( rSet ) );
1093 else
1095 m_pOldSet.reset( new SfxItemSet( rSet ) );
1099 SwUndoDefaultAttr::~SwUndoDefaultAttr()
1103 void SwUndoDefaultAttr::Undo( SwUndoIter& rUndoIter)
1105 SwDoc& rDoc = rUndoIter.GetDoc();
1106 if ( m_pOldSet.get() )
1108 SwUndoFmtAttrHelper aTmp(
1109 *const_cast<SwTxtFmtColl*>(rDoc.GetDfltTxtFmtColl()) );
1110 rDoc.SetDefault( *m_pOldSet );
1111 m_pOldSet.reset( 0 );
1112 if ( aTmp.GetUndo() )
1114 // transfer ownership of helper object's old set
1115 m_pOldSet = aTmp.GetUndo()->m_pOldSet;
1118 if ( m_pTabStop.get() )
1120 SvxTabStopItem* pOld = static_cast<SvxTabStopItem*>(
1121 rDoc.GetDefault( RES_PARATR_TABSTOP ).Clone() );
1122 rDoc.SetDefault( *m_pTabStop );
1123 m_pTabStop.reset( pOld );
1127 void SwUndoDefaultAttr::Redo( SwUndoIter& rUndoIter)
1129 Undo( rUndoIter );
1132 // -----------------------------------------------------
1134 SwUndoMoveLeftMargin::SwUndoMoveLeftMargin(
1135 const SwPaM& rPam, BOOL bFlag, BOOL bMod )
1136 : SwUndo( bFlag ? UNDO_INC_LEFTMARGIN : UNDO_DEC_LEFTMARGIN )
1137 , SwUndRng( rPam )
1138 , m_pHistory( new SwHistory )
1139 , m_bModulus( bMod )
1143 SwUndoMoveLeftMargin::~SwUndoMoveLeftMargin()
1147 void SwUndoMoveLeftMargin::Undo( SwUndoIter& rIter )
1149 SwDoc* pDoc = &rIter.GetDoc();
1150 BOOL bUndo = pDoc->DoesUndo();
1151 pDoc->DoUndo( FALSE );
1153 // restore old values
1154 m_pHistory->TmpRollback( pDoc, 0 );
1155 m_pHistory->SetTmpEnd( m_pHistory->Count() );
1157 pDoc->DoUndo( bUndo );
1158 SetPaM( rIter );
1161 void SwUndoMoveLeftMargin::Redo( SwUndoIter& rIter )
1163 SwDoc* pDoc = &rIter.GetDoc();
1164 SetPaM( rIter );
1165 pDoc->MoveLeftMargin( *rIter.pAktPam, GetId() == UNDO_INC_LEFTMARGIN,
1166 m_bModulus );
1169 void SwUndoMoveLeftMargin::Repeat( SwUndoIter& rIter )
1171 SwDoc* pDoc = &rIter.GetDoc();
1172 pDoc->MoveLeftMargin( *rIter.pAktPam, GetId() == UNDO_INC_LEFTMARGIN,
1173 m_bModulus );
1174 rIter.pLastUndoObj = this;
1177 // -----------------------------------------------------
1179 SwUndoChangeFootNote::SwUndoChangeFootNote(
1180 const SwPaM& rRange, const String& rTxt,
1181 USHORT nNum, bool bIsEndNote )
1182 : SwUndo( UNDO_CHGFTN ), SwUndRng( rRange )
1183 , m_pHistory( new SwHistory() )
1184 , m_Text( rTxt )
1185 , m_nNumber( nNum )
1186 , m_bEndNote( bIsEndNote )
1190 SwUndoChangeFootNote::~SwUndoChangeFootNote()
1194 void SwUndoChangeFootNote::Undo( SwUndoIter& rIter )
1196 SwDoc& rDoc = rIter.GetDoc();
1197 SetPaM( rIter );
1199 BOOL bUndo = rDoc.DoesUndo();
1200 rDoc.DoUndo( FALSE );
1202 m_pHistory->TmpRollback( &rDoc, 0 );
1203 m_pHistory->SetTmpEnd( m_pHistory->Count() );
1205 rDoc.GetFtnIdxs().UpdateAllFtn();
1207 SetPaM( rIter );
1208 rDoc.DoUndo( bUndo );
1211 void SwUndoChangeFootNote::Redo( SwUndoIter& rIter )
1213 SetPaM( rIter );
1214 rIter.GetDoc().SetCurFtn( *rIter.pAktPam, m_Text, m_nNumber, m_bEndNote );
1215 SetPaM( rIter );
1218 void SwUndoChangeFootNote::Repeat( SwUndoIter& rIter )
1220 SwDoc& rDoc = rIter.GetDoc();
1221 rDoc.SetCurFtn( *rIter.pAktPam, m_Text, m_nNumber, m_bEndNote );
1222 rIter.pLastUndoObj = this;
1226 // -----------------------------------------------------
1229 SwUndoFootNoteInfo::SwUndoFootNoteInfo( const SwFtnInfo &rInfo )
1230 : SwUndo( UNDO_FTNINFO )
1231 , m_pFootNoteInfo( new SwFtnInfo( rInfo ) )
1235 SwUndoFootNoteInfo::~SwUndoFootNoteInfo()
1239 void SwUndoFootNoteInfo::Undo( SwUndoIter &rIter )
1241 SwDoc &rDoc = rIter.GetDoc();
1242 SwFtnInfo *pInf = new SwFtnInfo( rDoc.GetFtnInfo() );
1243 rDoc.SetFtnInfo( *m_pFootNoteInfo );
1244 m_pFootNoteInfo.reset( pInf );
1247 void SwUndoFootNoteInfo::Redo( SwUndoIter &rIter )
1249 SwDoc &rDoc = rIter.GetDoc();
1250 SwFtnInfo *pInf = new SwFtnInfo( rDoc.GetFtnInfo() );
1251 rDoc.SetFtnInfo( *m_pFootNoteInfo );
1252 m_pFootNoteInfo.reset( pInf );
1256 // -----------------------------------------------------
1258 SwUndoEndNoteInfo::SwUndoEndNoteInfo( const SwEndNoteInfo &rInfo )
1259 : SwUndo( UNDO_FTNINFO )
1260 , m_pEndNoteInfo( new SwEndNoteInfo( rInfo ) )
1264 SwUndoEndNoteInfo::~SwUndoEndNoteInfo()
1268 void SwUndoEndNoteInfo::Undo( SwUndoIter &rIter )
1270 SwDoc &rDoc = rIter.GetDoc();
1271 SwEndNoteInfo *pInf = new SwEndNoteInfo( rDoc.GetEndNoteInfo() );
1272 rDoc.SetEndNoteInfo( *m_pEndNoteInfo );
1273 m_pEndNoteInfo.reset( pInf );
1276 void SwUndoEndNoteInfo::Redo( SwUndoIter &rIter )
1278 SwDoc &rDoc = rIter.GetDoc();
1279 SwEndNoteInfo *pInf = new SwEndNoteInfo( rDoc.GetEndNoteInfo() );
1280 rDoc.SetEndNoteInfo( *m_pEndNoteInfo );
1281 m_pEndNoteInfo.reset( pInf );
1284 // -----------------------------------------------------
1286 SwUndoDontExpandFmt::SwUndoDontExpandFmt( const SwPosition& rPos )
1287 : SwUndo( UNDO_DONTEXPAND )
1288 , m_nNodeIndex( rPos.nNode.GetIndex() )
1289 , m_nContentIndex( rPos.nContent.GetIndex() )
1293 void SwUndoDontExpandFmt::Undo( SwUndoIter& rIter )
1295 SwPaM* pPam = rIter.pAktPam;
1296 SwDoc* pDoc = pPam->GetDoc();
1298 SwPosition& rPos = *pPam->GetPoint();
1299 rPos.nNode = m_nNodeIndex;
1300 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), m_nContentIndex);
1301 pDoc->DontExpandFmt( rPos, FALSE );
1305 void SwUndoDontExpandFmt::Redo( SwUndoIter& rIter )
1307 SwPaM* pPam = rIter.pAktPam;
1308 SwDoc* pDoc = pPam->GetDoc();
1310 SwPosition& rPos = *pPam->GetPoint();
1311 rPos.nNode = m_nNodeIndex;
1312 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), m_nContentIndex);
1313 pDoc->DontExpandFmt( rPos );
1316 void SwUndoDontExpandFmt::Repeat( SwUndoIter& rIter )
1318 SwPaM* pPam = rIter.pAktPam;
1319 SwDoc* pDoc = pPam->GetDoc();
1320 pDoc->DontExpandFmt( *pPam->GetPoint() );