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