xref: /AOO41X/main/sw/source/core/undo/undobj1.cxx (revision efeef26f81c84063fb0a91bde3856d4a51172d90)
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