xref: /aoo41x/main/sw/source/core/undo/undobj1.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <svl/itemiter.hxx>
32 
33 #include <hintids.hxx>
34 #include <hints.hxx>
35 #include <fmtflcnt.hxx>
36 #include <fmtanchr.hxx>
37 #include <fmtcntnt.hxx>
38 #include <txtflcnt.hxx>
39 #include <frmfmt.hxx>
40 #include <flyfrm.hxx>
41 #include <UndoCore.hxx>
42 #include <UndoDraw.hxx>
43 #include <rolbck.hxx>	  	// fuer die Attribut History
44 #include <doc.hxx>
45 #include <docary.hxx>
46 #include <rootfrm.hxx>
47 #include <swundo.hxx>			// fuer die UndoIds
48 #include <pam.hxx>
49 #include <ndtxt.hxx>
50 // OD 26.06.2003 #108784#
51 #include <dcontact.hxx>
52 #include <ndole.hxx>
53 
54 
55 //---------------------------------------------------------------------
56 // SwUndoLayBase /////////////////////////////////////////////////////////
57 
58 SwUndoFlyBase::SwUndoFlyBase( SwFrmFmt* pFormat, SwUndoId nUndoId )
59 	: SwUndo( nUndoId ), pFrmFmt( pFormat )
60 {
61 }
62 
63 SwUndoFlyBase::~SwUndoFlyBase()
64 {
65 	if( bDelFmt )		// loeschen waehrend eines Undo's ??
66 		delete pFrmFmt;
67 }
68 
69 void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrm)
70 {
71     SwDoc *const pDoc = & rContext.GetDoc();
72 
73 	// ins Array wieder eintragen
74 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
75 	rFlyFmts.Insert( pFrmFmt, rFlyFmts.Count() );
76 
77     // OD 26.06.2003 #108784# - insert 'master' drawing object into drawing page
78     if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
79     {
80         SwDrawContact* pDrawContact =
81             static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
82         if ( pDrawContact )
83         {
84             pDrawContact->InsertMasterIntoDrawPage();
85             // --> OD 2005-01-31 #i40845# - follow-up of #i35635#
86             // move object to visible layer
87             pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() );
88             // <--
89         }
90     }
91 
92     SwFmtAnchor aAnchor( (RndStdIds)nRndId );
93 
94     if (FLY_AT_PAGE == nRndId)
95     {
96 		aAnchor.SetPageNum( (sal_uInt16)nNdPgPos );
97     }
98 	else
99 	{
100         SwPosition aNewPos(pDoc->GetNodes().GetEndOfContent());
101 		aNewPos.nNode = nNdPgPos;
102         if ((FLY_AS_CHAR == nRndId) || (FLY_AT_CHAR == nRndId))
103         {
104 			aNewPos.nContent.Assign( aNewPos.nNode.GetNode().GetCntntNode(),
105 									nCntPos );
106         }
107 		aAnchor.SetAnchor( &aNewPos );
108 	}
109 
110     pFrmFmt->SetFmtAttr( aAnchor );     // Anker neu setzen
111 
112 	if( RES_DRAWFRMFMT != pFrmFmt->Which() )
113 	{
114 		// Content holen und -Attribut neu setzen
115 		SwNodeIndex aIdx( pDoc->GetNodes() );
116 		RestoreSection( pDoc, &aIdx, SwFlyStartNode );
117         pFrmFmt->SetFmtAttr( SwFmtCntnt( aIdx.GetNode().GetStartNode() ));
118 	}
119 
120 	//JP 18.12.98: Bug 60505 - InCntntAttribut erst setzen, wenn der Inhalt
121 	//				vorhanden ist! Sonst wuerde das Layout den Fly vorher
122 	//				formatieren, aber keine Inhalt finden; so geschene bei
123 	//				Grafiken aus dem Internet
124     if (FLY_AS_CHAR == nRndId)
125     {
126 		// es muss mindestens das Attribut im TextNode stehen
127 		SwCntntNode* pCNd = aAnchor.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
128         ASSERT( pCNd->IsTxtNode(), "no Text Node at position." );
129         SwFmtFlyCnt aFmt( pFrmFmt );
130         static_cast<SwTxtNode*>(pCNd)->InsertItem( aFmt, nCntPos, nCntPos );
131     }
132 
133 	pFrmFmt->MakeFrms();
134 
135 	if( bShowSelFrm )
136     {
137         rContext.SetSelections(pFrmFmt, 0);
138     }
139 
140 	if( GetHistory() )
141 		GetHistory()->Rollback( pDoc );
142 
143 	switch( nRndId )
144     {
145     case FLY_AS_CHAR:
146     case FLY_AT_CHAR:
147         {
148 			const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
149 			nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
150 			nCntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
151 		}
152 		break;
153     case FLY_AT_PARA:
154 	case FLY_AT_FLY:
155 		{
156 			const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
157 			nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
158 		}
159 		break;
160     case FLY_AT_PAGE:
161 		break;
162 	}
163 	bDelFmt =  sal_False;
164 }
165 
166 void SwUndoFlyBase::DelFly( SwDoc* pDoc )
167 {
168 	bDelFmt = sal_True; 					// im DTOR das Format loeschen
169 	pFrmFmt->DelFrms(); 				// Frms vernichten.
170 
171 	// alle Uno-Objecte sollten sich jetzt abmelden
172 	{
173 		SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFrmFmt );
174 		pFrmFmt->ModifyNotification( &aMsgHint, &aMsgHint );
175 	}
176 
177 	if ( RES_DRAWFRMFMT != pFrmFmt->Which() )
178 	{
179 		// gibt es ueberhaupt Inhalt, dann sicher diesen
180 		const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
181 		ASSERT( rCntnt.GetCntntIdx(), "Fly ohne Inhalt" );
182 
183 		SaveSection( pDoc, *rCntnt.GetCntntIdx() );
184 		((SwFmtCntnt&)rCntnt).SetNewCntntIdx( (const SwNodeIndex*)0 );
185 	}
186     // OD 02.07.2003 #108784# - remove 'master' drawing object from drawing page
187     else if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
188     {
189         SwDrawContact* pDrawContact =
190             static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
191         if ( pDrawContact )
192         {
193             pDrawContact->RemoveMasterFromDrawPage();
194         }
195     }
196 
197 	const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
198 	const SwPosition* pPos = rAnchor.GetCntntAnchor();
199 	// die Positionen im Nodes-Array haben sich verschoben
200     nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
201     if (FLY_AS_CHAR == nRndId)
202     {
203 		nNdPgPos = pPos->nNode.GetIndex();
204 		nCntPos = pPos->nContent.GetIndex();
205         SwTxtNode *const pTxtNd = pPos->nNode.GetNode().GetTxtNode();
206         OSL_ENSURE(pTxtNd, "no Textnode");
207         SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
208             pTxtNd->GetTxtAttrForCharAt( nCntPos, RES_TXTATR_FLYCNT ) );
209 		// Attribut steht noch im TextNode, loeschen
210 		if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFrmFmt )
211 		{
212 			// Pointer auf 0, nicht loeschen
213 			((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt();
214 			SwIndex aIdx( pPos->nContent );
215             pTxtNd->EraseText( aIdx, 1 );
216         }
217     }
218     else if (FLY_AT_CHAR == nRndId)
219     {
220 		nNdPgPos = pPos->nNode.GetIndex();
221 		nCntPos = pPos->nContent.GetIndex();
222     }
223     else if ((FLY_AT_PARA == nRndId) || (FLY_AT_FLY == nRndId))
224     {
225 		nNdPgPos = pPos->nNode.GetIndex();
226     }
227 	else
228     {
229 		nNdPgPos = rAnchor.GetPageNum();
230     }
231 
232     pFrmFmt->ResetFmtAttr( RES_ANCHOR );        // Anchor loeschen
233 
234 
235 	// aus dem Array austragen
236 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
237 	rFlyFmts.Remove( rFlyFmts.GetPos( pFrmFmt ));
238 }
239 
240 // SwUndoInsLayFmt ///////////////////////////////////////////////////////
241 
242 SwUndoInsLayFmt::SwUndoInsLayFmt( SwFrmFmt* pFormat, sal_uLong nNodeIdx, xub_StrLen nCntIdx )
243 	: SwUndoFlyBase( pFormat, RES_DRAWFRMFMT == pFormat->Which() ?
244                                             UNDO_INSDRAWFMT : UNDO_INSLAYFMT ),
245     mnCrsrSaveIndexPara( nNodeIdx ), mnCrsrSaveIndexPos( nCntIdx )
246 {
247 	const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
248 	nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
249 	bDelFmt = sal_False;
250 	switch( nRndId )
251     {
252     case FLY_AT_PAGE:
253 		nNdPgPos = rAnchor.GetPageNum();
254 		break;
255     case FLY_AT_PARA:
256 	case FLY_AT_FLY:
257 		nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
258 		break;
259     case FLY_AS_CHAR:
260     case FLY_AT_CHAR:
261         {
262 			const SwPosition* pPos = rAnchor.GetCntntAnchor();
263 			nCntPos = pPos->nContent.GetIndex();
264 			nNdPgPos = pPos->nNode.GetIndex();
265 		}
266 		break;
267 	default:
268 		ASSERT( sal_False, "Was denn fuer ein FlyFrame?" );
269 	}
270 }
271 
272 SwUndoInsLayFmt::~SwUndoInsLayFmt()
273 {
274 }
275 
276 void SwUndoInsLayFmt::UndoImpl(::sw::UndoRedoContext & rContext)
277 {
278     SwDoc & rDoc(rContext.GetDoc());
279 	const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
280 	if( rCntnt.GetCntntIdx() ) 	// kein Inhalt
281     {
282         bool bRemoveIdx = true;
283         if( mnCrsrSaveIndexPara > 0 )
284         {
285             SwTxtNode *const pNode =
286                 rDoc.GetNodes()[mnCrsrSaveIndexPara]->GetTxtNode();
287 			if( pNode )
288 			{
289                 SwNodeIndex aIdx( rDoc.GetNodes(),
290                         rCntnt.GetCntntIdx()->GetIndex() );
291                 SwNodeIndex aEndIdx( rDoc.GetNodes(),
292                         aIdx.GetNode().EndOfSectionIndex() );
293 				SwIndex aIndex( pNode, mnCrsrSaveIndexPos );
294 				SwPosition aPos( *pNode, aIndex );
295                 rDoc.CorrAbs( aIdx, aEndIdx, aPos, sal_True );
296                 bRemoveIdx = false;
297 			}
298         }
299         if( bRemoveIdx )
300         {
301             RemoveIdxFromSection( rDoc, rCntnt.GetCntntIdx()->GetIndex() );
302         }
303     }
304     DelFly(& rDoc);
305 }
306 
307 void SwUndoInsLayFmt::RedoImpl(::sw::UndoRedoContext & rContext)
308 {
309     InsFly(rContext);
310 }
311 
312 void SwUndoInsLayFmt::RepeatImpl(::sw::RepeatContext & rContext)
313 {
314     SwDoc *const pDoc = & rContext.GetDoc();
315 	// erfrage und setze den Anker neu
316 	SwFmtAnchor aAnchor( pFrmFmt->GetAnchor() );
317     if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
318         (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
319         (FLY_AS_CHAR == aAnchor.GetAnchorId()))
320     {
321         SwPosition aPos( *rContext.GetRepeatPaM().GetPoint() );
322         if (FLY_AT_PARA == aAnchor.GetAnchorId())
323         {
324 			aPos.nContent.Assign( 0, 0 );
325         }
326 		aAnchor.SetAnchor( &aPos );
327 	}
328 	else if( FLY_AT_FLY == aAnchor.GetAnchorId() )
329 	{
330         SwStartNode const*const pSttNd =
331             rContext.GetRepeatPaM().GetNode()->FindFlyStartNode();
332 		if( pSttNd )
333 		{
334 			SwPosition aPos( *pSttNd );
335 			aAnchor.SetAnchor( &aPos );
336 		}
337 		else
338 		{
339 			return ;
340         }
341     }
342     else if (FLY_AT_PAGE == aAnchor.GetAnchorId())
343     {
344 		aAnchor.SetPageNum( pDoc->GetCurrentLayout()->GetCurrPage( &rContext.GetRepeatPaM() ));
345 	}
346 	else {
347 		ASSERT( sal_False, "was fuer ein Anker ist es denn nun?" );
348     }
349 
350     SwFrmFmt* pFlyFmt = pDoc->CopyLayoutFmt( *pFrmFmt, aAnchor, true, true );
351     (void) pFlyFmt;
352 //FIXME nobody ever did anything with this selection:
353 //    rContext.SetSelections(pFlyFmt, 0);
354 }
355 
356 // #111827#
357 String SwUndoInsLayFmt::GetComment() const
358 {
359     String aResult;
360 
361     // HACK: disable caching:
362     // the SfxUndoManager calls GetComment() too early: the pFrmFmt does not
363     // have a SwDrawContact yet, so it will fall back to SwUndo::GetComment(),
364     // which sets pComment to a wrong value.
365 //    if (! pComment)
366     if (true)
367     {
368         /*
369           If frame format is present and has an SdrObject use the undo
370           comment of the SdrObject. Otherwise use the default comment.
371         */
372 
373         bool bDone = false;
374         if (pFrmFmt)
375         {
376             const SdrObject * pSdrObj = pFrmFmt->FindSdrObject();
377             if ( pSdrObj )
378             {
379                 aResult = SdrUndoNewObj::GetComment( *pSdrObj );
380                 bDone = true;
381             }
382         }
383 
384         if (! bDone)
385             aResult = SwUndo::GetComment();
386     }
387     else
388         aResult = *pComment;
389 
390     return aResult;
391 }
392 
393 // SwUndoDelLayFmt ///////////////////////////////////////////////////////
394 
395 static SwUndoId
396 lcl_GetSwUndoId(SwFrmFmt *const pFrmFmt)
397 {
398     if (RES_DRAWFRMFMT != pFrmFmt->Which())
399     {
400         const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
401         OSL_ENSURE( rCntnt.GetCntntIdx(), "Fly without content" );
402 
403         SwNodeIndex firstNode(*rCntnt.GetCntntIdx(), 1);
404         SwNoTxtNode *const pNoTxtNode(firstNode.GetNode().GetNoTxtNode());
405         if (pNoTxtNode && pNoTxtNode->IsGrfNode())
406         {
407             return UNDO_DELGRF;
408         }
409         else if (pNoTxtNode && pNoTxtNode->IsOLENode())
410         {
411             // surprisingly not UNDO_DELOLE, which does not seem to work
412             return UNDO_DELETE;
413         }
414     }
415     return UNDO_DELLAYFMT;
416 }
417 
418 SwUndoDelLayFmt::SwUndoDelLayFmt( SwFrmFmt* pFormat )
419     : SwUndoFlyBase( pFormat, lcl_GetSwUndoId(pFormat) )
420     , bShowSelFrm( sal_True )
421 {
422 	SwDoc* pDoc = pFormat->GetDoc();
423 	DelFly( pDoc );
424 }
425 
426 SwRewriter SwUndoDelLayFmt::GetRewriter() const
427 {
428     SwRewriter aRewriter;
429 
430     SwDoc * pDoc = pFrmFmt->GetDoc();
431 
432     if (pDoc)
433     {
434         SwNodeIndex* pIdx = GetMvSttIdx();
435         if( 1 == GetMvNodeCnt() && pIdx)
436         {
437             SwNode *const pNd = & pIdx->GetNode();
438 
439             if ( pNd->IsNoTxtNode() && pNd->IsOLENode())
440             {
441                 SwOLENode * pOLENd = pNd->GetOLENode();
442 
443                 aRewriter.AddRule(UNDO_ARG1, pOLENd->GetDescription());
444             }
445         }
446     }
447 
448     return aRewriter;
449 }
450 
451 void SwUndoDelLayFmt::UndoImpl(::sw::UndoRedoContext & rContext)
452 {
453     InsFly( rContext, bShowSelFrm );
454 }
455 
456 void SwUndoDelLayFmt::RedoImpl(::sw::UndoRedoContext & rContext)
457 {
458     SwDoc & rDoc(rContext.GetDoc());
459 	const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
460 	if( rCntnt.GetCntntIdx() ) 	// kein Inhalt
461     {
462         RemoveIdxFromSection(rDoc, rCntnt.GetCntntIdx()->GetIndex());
463     }
464 
465     DelFly(& rDoc);
466 }
467 
468 void SwUndoDelLayFmt::RedoForRollback()
469 {
470 	const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
471 	if( rCntnt.GetCntntIdx() ) 	// kein Inhalt
472 		RemoveIdxFromSection( *pFrmFmt->GetDoc(),
473 								rCntnt.GetCntntIdx()->GetIndex() );
474 
475 	DelFly( pFrmFmt->GetDoc() );
476 }
477 
478 // SwUndoSetFlyFmt ///////////////////////////////////////////////////////
479 
480 SwUndoSetFlyFmt::SwUndoSetFlyFmt( SwFrmFmt& rFlyFmt, SwFrmFmt& rNewFrmFmt )
481 	: SwUndo( UNDO_SETFLYFRMFMT ), SwClient( &rFlyFmt ), pFrmFmt( &rFlyFmt ),
482 	pOldFmt( (SwFrmFmt*)rFlyFmt.DerivedFrom() ), pNewFmt( &rNewFrmFmt ),
483 	pItemSet( new SfxItemSet( *rFlyFmt.GetAttrSet().GetPool(),
484 								rFlyFmt.GetAttrSet().GetRanges() )),
485 	nOldNode( 0 ), nNewNode( 0 ),
486 	nOldCntnt( 0 ), nNewCntnt( 0 ),
487 	nOldAnchorTyp( 0 ),	nNewAnchorTyp( 0 ), bAnchorChgd( sal_False )
488 {
489 }
490 
491 SwRewriter SwUndoSetFlyFmt::GetRewriter() const
492 {
493     SwRewriter aRewriter;
494 
495     if (pNewFmt)
496         aRewriter.AddRule(UNDO_ARG1, pNewFmt->GetName());
497 
498     return aRewriter;
499 }
500 
501 
502 SwUndoSetFlyFmt::~SwUndoSetFlyFmt()
503 {
504 	delete pItemSet;
505 }
506 
507 void SwUndoSetFlyFmt::DeRegisterFromFormat( SwFmt& rFmt )
508 {
509     rFmt.Remove(this);
510 }
511 
512 void SwUndoSetFlyFmt::GetAnchor( SwFmtAnchor& rAnchor,
513 								sal_uLong nNode, xub_StrLen nCntnt )
514 {
515 	RndStdIds nAnchorTyp = rAnchor.GetAnchorId();
516     if (FLY_AT_PAGE != nAnchorTyp)
517     {
518 		SwNode* pNd = pFrmFmt->GetDoc()->GetNodes()[ nNode ];
519 
520 		if( FLY_AT_FLY == nAnchorTyp
521 				? ( !pNd->IsStartNode() || SwFlyStartNode !=
522 					((SwStartNode*)pNd)->GetStartNodeType() )
523 				: !pNd->IsTxtNode() )
524         {
525             pNd = 0;    // invalid position
526         }
527 		else
528 		{
529 			SwPosition aPos( *pNd );
530             if ((FLY_AS_CHAR == nAnchorTyp) ||
531                 (FLY_AT_CHAR == nAnchorTyp))
532             {
533                 if ( nCntnt > static_cast<SwTxtNode*>(pNd)->GetTxt().Len() )
534                 {
535                     pNd = 0;    // invalid position
536                 }
537                 else
538                 {
539                     aPos.nContent.Assign(static_cast<SwTxtNode*>(pNd), nCntnt);
540                 }
541             }
542             if ( pNd )
543             {
544 				rAnchor.SetAnchor( &aPos );
545             }
546         }
547 
548 		if( !pNd )
549 		{
550 			// ungueltige Position - setze auf 1. Seite
551             rAnchor.SetType( FLY_AT_PAGE );
552 			rAnchor.SetPageNum( 1 );
553 		}
554 	}
555 	else
556 		rAnchor.SetPageNum( nCntnt );
557 }
558 
559 void SwUndoSetFlyFmt::UndoImpl(::sw::UndoRedoContext & rContext)
560 {
561     SwDoc & rDoc = rContext.GetDoc();
562 
563 	// ist das neue Format noch vorhanden ??
564 	if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmtPtr)pOldFmt ) )
565 	{
566 		if( bAnchorChgd )
567 			pFrmFmt->DelFrms();
568 
569 		if( pFrmFmt->DerivedFrom() != pOldFmt )
570 			pFrmFmt->SetDerivedFrom( pOldFmt );
571 
572 		SfxItemIter aIter( *pItemSet );
573 		const SfxPoolItem* pItem = aIter.GetCurItem();
574 		while( pItem )
575 		{
576 			if( IsInvalidItem( pItem ))
577                 pFrmFmt->ResetFmtAttr( pItemSet->GetWhichByPos(
578 										aIter.GetCurPos() ));
579 			else
580                 pFrmFmt->SetFmtAttr( *pItem );
581 
582 			if( aIter.IsAtEnd() )
583 				break;
584 			pItem = aIter.NextItem();
585 		}
586 
587 		if( bAnchorChgd )
588 		{
589 			const SwFmtAnchor& rOldAnch = pFrmFmt->GetAnchor();
590             if (FLY_AS_CHAR == rOldAnch.GetAnchorId())
591             {
592 				// Bei InCntnt's wird es spannend: Das TxtAttribut muss
593 				// vernichtet werden. Leider reisst dies neben den Frms
594 				// auch noch das Format mit in sein Grab. Um dass zu
595 				// unterbinden loesen wir vorher die Verbindung zwischen
596 				// Attribut und Format.
597 				const SwPosition *pPos = rOldAnch.GetCntntAnchor();
598 				SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
599 				ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
600 				const xub_StrLen nIdx = pPos->nContent.GetIndex();
601                 SwTxtAttr * pHnt = pTxtNode->GetTxtAttrForCharAt(
602                         nIdx, RES_TXTATR_FLYCNT );
603 				ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
604 							"Missing FlyInCnt-Hint." );
605 				ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt,
606 							"Wrong TxtFlyCnt-Hint." );
607                 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
608 
609 				// Die Verbindung ist geloest, jetzt muss noch das Attribut
610 				// vernichtet werden.
611                 pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
612             }
613 
614 			// Anker umsetzen
615 			SwFmtAnchor aNewAnchor( (RndStdIds) nOldAnchorTyp );
616 			GetAnchor( aNewAnchor, nOldNode, nOldCntnt );
617             pFrmFmt->SetFmtAttr( aNewAnchor );
618 
619             if (FLY_AS_CHAR == aNewAnchor.GetAnchorId())
620             {
621 				SwPosition* pPos = (SwPosition*)aNewAnchor.GetCntntAnchor();
622                 SwFmtFlyCnt aFmt( pFrmFmt );
623                 pPos->nNode.GetNode().GetTxtNode()->InsertItem( aFmt,
624                     nOldCntnt, 0 );
625             }
626 
627 			pFrmFmt->MakeFrms();
628 		}
629         rContext.SetSelections(pFrmFmt, 0);
630     }
631 }
632 
633 void SwUndoSetFlyFmt::RedoImpl(::sw::UndoRedoContext & rContext)
634 {
635     SwDoc & rDoc = rContext.GetDoc();
636 
637 	// ist das neue Format noch vorhanden ??
638 	if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmtPtr)pNewFmt ) )
639 	{
640 
641 		if( bAnchorChgd )
642 		{
643 			SwFmtAnchor aNewAnchor( (RndStdIds) nNewAnchorTyp );
644 			GetAnchor( aNewAnchor, nNewNode, nNewCntnt );
645 			SfxItemSet aSet( rDoc.GetAttrPool(), aFrmFmtSetRange );
646 			aSet.Put( aNewAnchor );
647 			rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, &aSet );
648 		}
649 		else
650 			rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, 0 );
651 
652         rContext.SetSelections(pFrmFmt, 0);
653     }
654 }
655 
656 void SwUndoSetFlyFmt::PutAttr( sal_uInt16 nWhich, const SfxPoolItem* pItem )
657 {
658 	if( pItem && pItem != GetDfltAttr( nWhich ) )
659 	{
660 		// Sonderbehandlung fuer den Anchor
661 		if( RES_ANCHOR == nWhich )
662 		{
663 			// nur den 1. Ankerwechsel vermerken
664 			ASSERT( !bAnchorChgd, "mehrfacher Ankerwechsel nicht erlaubt!" );
665 
666 			bAnchorChgd = sal_True;
667 
668 			const SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
669 			switch( nOldAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
670             {
671             case FLY_AS_CHAR:
672             case FLY_AT_CHAR:
673 				nOldCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
674             case FLY_AT_PARA:
675 			case FLY_AT_FLY:
676 				nOldNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
677 				break;
678 
679 			default:
680 				nOldCntnt = pAnchor->GetPageNum();
681 			}
682 
683 			pAnchor = (SwFmtAnchor*)&pFrmFmt->GetAnchor();
684 			switch( nNewAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
685 			{
686             case FLY_AS_CHAR:
687             case FLY_AT_CHAR:
688 				nNewCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
689             case FLY_AT_PARA:
690 			case FLY_AT_FLY:
691 				nNewNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
692 				break;
693 
694 			default:
695 				nNewCntnt = pAnchor->GetPageNum();
696 			}
697 		}
698 		else
699 			pItemSet->Put( *pItem );
700 	}
701 	else
702 		pItemSet->InvalidateItem( nWhich );
703 }
704 
705 void SwUndoSetFlyFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* )
706 {
707 	if( pOld )
708 	{
709 		sal_uInt16 nWhich = pOld->Which();
710 
711 		if( nWhich < POOLATTR_END )
712 			PutAttr( nWhich, pOld );
713 		else if( RES_ATTRSET_CHG == nWhich )
714 		{
715 			SfxItemIter aIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
716 			const SfxPoolItem* pItem = aIter.GetCurItem();
717 			while( pItem )
718 			{
719 				PutAttr( pItem->Which(), pItem );
720 				if( aIter.IsAtEnd() )
721 					break;
722 				pItem = aIter.NextItem();
723 			}
724 		}
725 	}
726 }
727 
728