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