xref: /aoo41x/main/sw/source/core/undo/undraw.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 <UndoDraw.hxx>
32 
33 #include <rtl/string.h>
34 #include <rtl/memory.h>
35 
36 #include <rtl/string.h>
37 #include <svx/svdogrp.hxx>
38 #include <svx/svdundo.hxx>
39 #include <svx/svdpage.hxx>
40 #include <svx/svdmark.hxx>
41 
42 #include <hintids.hxx>
43 #include <hints.hxx>
44 #include <fmtanchr.hxx>
45 #include <fmtflcnt.hxx>
46 #include <txtflcnt.hxx>
47 #include <frmfmt.hxx>
48 #include <doc.hxx>
49 #include <IDocumentUndoRedo.hxx>
50 #include <docary.hxx>
51 #include <frame.hxx>
52 #include <swundo.hxx>			// fuer die UndoIds
53 #include <pam.hxx>
54 #include <ndtxt.hxx>
55 #include <UndoCore.hxx>
56 #include <dcontact.hxx>
57 #include <dview.hxx>
58 #include <rootfrm.hxx>
59 #include <viewsh.hxx>
60 
61 
62 struct SwUndoGroupObjImpl
63 {
64 	SwDrawFrmFmt* pFmt;
65 	SdrObject* pObj;
66 	sal_uLong nNodeIdx;
67 };
68 
69 
70 // Draw-Objecte
71 
72 IMPL_LINK( SwDoc, AddDrawUndo, SdrUndoAction *, pUndo )
73 {
74 #if OSL_DEBUG_LEVEL > 1
75 	sal_uInt16 nId = pUndo->GetId();
76     (void)nId;
77 	String sComment( pUndo->GetComment() );
78 #endif
79 
80     if (GetIDocumentUndoRedo().DoesUndo() &&
81         GetIDocumentUndoRedo().DoesDrawUndo())
82     {
83 		const SdrMarkList* pMarkList = 0;
84 		ViewShell* pSh = GetCurrentViewShell();
85 		if( pSh && pSh->HasDrawView() )
86 			pMarkList = &pSh->GetDrawView()->GetMarkedObjectList();
87 
88         GetIDocumentUndoRedo().AppendUndo( new SwSdrUndo(pUndo, pMarkList) );
89 	}
90 	else
91 		delete pUndo;
92 	return 0;
93 }
94 
95 SwSdrUndo::SwSdrUndo( SdrUndoAction* pUndo, const SdrMarkList* pMrkLst )
96 	: SwUndo( UNDO_DRAWUNDO ), pSdrUndo( pUndo )
97 {
98 	if( pMrkLst && pMrkLst->GetMarkCount() )
99 		pMarkList = new SdrMarkList( *pMrkLst );
100 	else
101 		pMarkList = 0;
102 }
103 
104 SwSdrUndo::~SwSdrUndo()
105 {
106 	delete pSdrUndo;
107 	delete pMarkList;
108 }
109 
110 void SwSdrUndo::UndoImpl(::sw::UndoRedoContext & rContext)
111 {
112 	pSdrUndo->Undo();
113     rContext.SetSelections(0, pMarkList);
114 }
115 
116 void SwSdrUndo::RedoImpl(::sw::UndoRedoContext & rContext)
117 {
118 	pSdrUndo->Redo();
119     rContext.SetSelections(0, pMarkList);
120 }
121 
122 String SwSdrUndo::GetComment() const
123 {
124 	return pSdrUndo->GetComment();
125 }
126 
127 //--------------------------------------------
128 
129 void lcl_SendRemoveToUno( SwFmt& rFmt )
130 {
131 	SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, &rFmt );
132 	rFmt.ModifyNotification( &aMsgHint, &aMsgHint );
133 }
134 
135 void lcl_SaveAnchor( SwFrmFmt* pFmt, sal_uLong& rNodePos )
136 {
137 	const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
138     if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
139         (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
140         (FLY_AT_FLY  == rAnchor.GetAnchorId()) ||
141         (FLY_AS_CHAR == rAnchor.GetAnchorId()))
142     {
143 		rNodePos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
144 		xub_StrLen nCntntPos = 0;
145 
146         if (FLY_AS_CHAR == rAnchor.GetAnchorId())
147         {
148 			nCntntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
149 
150 			// destroy TextAttribute
151 			SwTxtNode *pTxtNd = pFmt->GetDoc()->GetNodes()[ rNodePos ]->GetTxtNode();
152 			ASSERT( pTxtNd, "No text node found!" );
153             SwTxtFlyCnt* pAttr = static_cast<SwTxtFlyCnt*>(
154                 pTxtNd->GetTxtAttrForCharAt( nCntntPos, RES_TXTATR_FLYCNT ));
155 			// attribute still in text node, delete
156 			if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFmt )
157 			{
158 				// just set pointer to 0, don't delete
159 				((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt();
160 				SwIndex aIdx( pTxtNd, nCntntPos );
161                 pTxtNd->EraseText( aIdx, 1 );
162             }
163         }
164         else if (FLY_AT_CHAR == rAnchor.GetAnchorId())
165         {
166 			nCntntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
167         }
168 
169         pFmt->SetFmtAttr( SwFmtAnchor( rAnchor.GetAnchorId(), nCntntPos ) );
170 	}
171 }
172 
173 void lcl_RestoreAnchor( SwFrmFmt* pFmt, sal_uLong& rNodePos )
174 {
175 	const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
176     if ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
177         (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
178         (FLY_AT_FLY  == rAnchor.GetAnchorId()) ||
179         (FLY_AS_CHAR == rAnchor.GetAnchorId()))
180     {
181 		xub_StrLen nCntntPos = rAnchor.GetPageNum();
182 		SwNodes& rNds = pFmt->GetDoc()->GetNodes();
183 
184 		SwNodeIndex aIdx( rNds, rNodePos );
185 		SwPosition aPos( aIdx );
186 
187 		SwFmtAnchor aTmp( rAnchor.GetAnchorId() );
188         if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) ||
189             (FLY_AT_CHAR == rAnchor.GetAnchorId()))
190         {
191 			aPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), nCntntPos );
192         }
193 		aTmp.SetAnchor( &aPos );
194         pFmt->SetFmtAttr( aTmp );
195 
196         if (FLY_AS_CHAR == rAnchor.GetAnchorId())
197         {
198 			SwTxtNode *pTxtNd = aIdx.GetNode().GetTxtNode();
199             ASSERT( pTxtNd, "no Text Node" );
200             SwFmtFlyCnt aFmt( pFmt );
201             pTxtNd->InsertItem( aFmt, nCntntPos, nCntntPos );
202         }
203     }
204 }
205 
206 SwUndoDrawGroup::SwUndoDrawGroup( sal_uInt16 nCnt )
207 	: SwUndo( UNDO_DRAWGROUP ), nSize( nCnt + 1 ), bDelFmt( sal_True )
208 {
209 	pObjArr = new SwUndoGroupObjImpl[ nSize ];
210 }
211 
212 SwUndoDrawGroup::~SwUndoDrawGroup()
213 {
214 	if( bDelFmt )
215 	{
216 		SwUndoGroupObjImpl* pTmp = pObjArr + 1;
217 		for( sal_uInt16 n = 1; n < nSize; ++n, ++pTmp )
218 			delete pTmp->pFmt;
219 	}
220 	else
221 		delete pObjArr->pFmt;
222 
223 	delete [] pObjArr;
224 }
225 
226 void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &)
227 {
228 	bDelFmt = sal_False;
229 
230 	// save group object
231 	SwDrawFrmFmt* pFmt = pObjArr->pFmt;
232 	SwDrawContact* pDrawContact = (SwDrawContact*)pFmt->FindContactObj();
233 	SdrObject* pObj	= pDrawContact->GetMaster();
234 	pObjArr->pObj = pObj;
235 
236 	// object will destroy itself
237 	pDrawContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
238 	pObj->SetUserCall( 0 );
239 
240 	::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
241 
242 	// notify UNO objects to decouple
243 	::lcl_SendRemoveToUno( *pFmt );
244 
245 	// remove from array
246 	SwDoc* pDoc = pFmt->GetDoc();
247 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
248 	rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
249 
250 	for( sal_uInt16 n = 1; n < nSize; ++n )
251 	{
252 		SwUndoGroupObjImpl& rSave = *( pObjArr + n );
253 
254 		::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
255 		rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
256 
257 		pObj = rSave.pObj;
258 
259 		SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, pObj );
260 		pContact->ConnectToLayout();
261         // #i45718# - follow-up of #i35635# move object to visible layer
262         pContact->MoveObjToVisibleLayer( pObj );
263         // #i45952# - notify that position attributes are already set
264         ASSERT( rSave.pFmt->ISA(SwDrawFrmFmt),
265                 "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
266         if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
267         {
268             static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
269         }
270 	}
271 }
272 
273 void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &)
274 {
275 	bDelFmt = sal_True;
276 
277 	// remove from array
278 	SwDoc* pDoc = pObjArr->pFmt->GetDoc();
279 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
280 	SdrObject* pObj;
281 
282 	for( sal_uInt16 n = 1; n < nSize; ++n )
283 	{
284 		SwUndoGroupObjImpl& rSave = *( pObjArr + n );
285 
286 		pObj = rSave.pObj;
287 
288 		SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
289 
290 	    // object will destroy itself
291 		pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
292 		pObj->SetUserCall( 0 );
293 
294 		::lcl_SaveAnchor( rSave.pFmt, rSave.nNodeIdx );
295 
296     	// notify UNO objects to decouple
297 		::lcl_SendRemoveToUno( *rSave.pFmt );
298 
299 		rFlyFmts.Remove( rFlyFmts.GetPos( rSave.pFmt ));
300 	}
301 
302 	// re-insert group object
303 	::lcl_RestoreAnchor( pObjArr->pFmt, pObjArr->nNodeIdx );
304 	rFlyFmts.Insert( pObjArr->pFmt, rFlyFmts.Count() );
305 
306 	SwDrawContact *pContact = new SwDrawContact( pObjArr->pFmt, pObjArr->pObj );
307     // #i26791# - correction: connect object to layout
308     pContact->ConnectToLayout();
309     // #i45718# - follow-up of #i35635# move object to visible layer
310     pContact->MoveObjToVisibleLayer( pObjArr->pObj );
311     // #i45952# - notify that position attributes are already set
312     ASSERT( pObjArr->pFmt->ISA(SwDrawFrmFmt),
313             "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
314     if ( pObjArr->pFmt->ISA(SwDrawFrmFmt) )
315     {
316         static_cast<SwDrawFrmFmt*>(pObjArr->pFmt)->PosAttrSet();
317     }
318 }
319 
320 void SwUndoDrawGroup::AddObj( sal_uInt16 nPos, SwDrawFrmFmt* pFmt, SdrObject* pObj )
321 {
322 	SwUndoGroupObjImpl& rSave = *( pObjArr + nPos + 1 );
323 	rSave.pObj = pObj;
324 	rSave.pFmt = pFmt;
325 	::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
326 
327    	// notify UNO objects to decouple
328 	::lcl_SendRemoveToUno( *pFmt );
329 
330 	// remove from array
331 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pFmt->GetDoc()->GetSpzFrmFmts();
332 	rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
333 }
334 
335 void SwUndoDrawGroup::SetGroupFmt( SwDrawFrmFmt* pFmt )
336 {
337 	pObjArr->pObj = 0;
338 	pObjArr->pFmt = pFmt;
339 }
340 
341 
342 // ------------------------------
343 
344 SwUndoDrawUnGroup::SwUndoDrawUnGroup( SdrObjGroup* pObj )
345 	: SwUndo( UNDO_DRAWUNGROUP ), bDelFmt( sal_False )
346 {
347 	nSize = (sal_uInt16)pObj->GetSubList()->GetObjCount() + 1;
348 	pObjArr = new SwUndoGroupObjImpl[ nSize ];
349 
350 	SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
351 	SwDrawFrmFmt* pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
352 
353 	pObjArr->pObj = pObj;
354 	pObjArr->pFmt = pFmt;
355 
356     // object will destroy itself
357 	pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
358 	pObj->SetUserCall( 0 );
359 
360 	::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
361 
362    	// notify UNO objects to decouple
363 	::lcl_SendRemoveToUno( *pFmt );
364 
365 	// remove from array
366 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pFmt->GetDoc()->GetSpzFrmFmts();
367 	rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
368 }
369 
370 SwUndoDrawUnGroup::~SwUndoDrawUnGroup()
371 {
372 	if( bDelFmt )
373 	{
374 		SwUndoGroupObjImpl* pTmp = pObjArr + 1;
375 		for( sal_uInt16 n = 1; n < nSize; ++n, ++pTmp )
376 			delete pTmp->pFmt;
377 	}
378 	else
379 		delete pObjArr->pFmt;
380 
381 	delete [] pObjArr;
382 }
383 
384 void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & rContext)
385 {
386 	bDelFmt = sal_True;
387 
388     SwDoc *const pDoc = & rContext.GetDoc();
389 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
390 
391     // remove from array
392 	for( sal_uInt16 n = 1; n < nSize; ++n )
393 	{
394 		SwUndoGroupObjImpl& rSave = *( pObjArr + n );
395 
396 		::lcl_SaveAnchor( rSave.pFmt, rSave.nNodeIdx );
397 
398        	// notify UNO objects to decouple
399 		::lcl_SendRemoveToUno( *rSave.pFmt );
400 
401 		rFlyFmts.Remove( rFlyFmts.GetPos( rSave.pFmt ));
402 	}
403 
404 	// re-insert group object
405 	::lcl_RestoreAnchor( pObjArr->pFmt, pObjArr->nNodeIdx );
406 	rFlyFmts.Insert( pObjArr->pFmt, rFlyFmts.Count() );
407 
408 	SwDrawContact *pContact = new SwDrawContact( pObjArr->pFmt, pObjArr->pObj );
409 	pContact->ConnectToLayout();
410     // #i45718# - follow-up of #i35635# move object to visible layer
411     pContact->MoveObjToVisibleLayer( pObjArr->pObj );
412     // #i45952# - notify that position attributes are already set
413     ASSERT( pObjArr->pFmt->ISA(SwDrawFrmFmt),
414             "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
415     if ( pObjArr->pFmt->ISA(SwDrawFrmFmt) )
416     {
417         static_cast<SwDrawFrmFmt*>(pObjArr->pFmt)->PosAttrSet();
418     }
419 }
420 
421 void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &)
422 {
423 	bDelFmt = sal_False;
424 
425 	// save group object
426 	SwDrawFrmFmt* pFmt = pObjArr->pFmt;
427 	SwDrawContact* pContact = (SwDrawContact*)pFmt->FindContactObj();
428 
429 	    // object will destroy itself
430 	pContact->Changed( *pObjArr->pObj, SDRUSERCALL_DELETE,
431 		pObjArr->pObj->GetLastBoundRect() );
432 	pObjArr->pObj->SetUserCall( 0 );
433 
434 	::lcl_SaveAnchor( pFmt, pObjArr->nNodeIdx );
435 
436    	// notify UNO objects to decouple
437 	::lcl_SendRemoveToUno( *pFmt );
438 
439 	// remove from array
440 	SwDoc* pDoc = pFmt->GetDoc();
441 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
442 	rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
443 
444 	for( sal_uInt16 n = 1; n < nSize; ++n )
445 	{
446 		SwUndoGroupObjImpl& rSave = *( pObjArr + n );
447 
448 		::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
449 		rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
450 
451         // #i45952# - notify that position attributes are already set
452         ASSERT( rSave.pFmt->ISA(SwDrawFrmFmt),
453                 "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
454         if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
455         {
456             static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
457         }
458 	}
459 }
460 
461 void SwUndoDrawUnGroup::AddObj( sal_uInt16 nPos, SwDrawFrmFmt* pFmt )
462 {
463 	SwUndoGroupObjImpl& rSave = *( pObjArr + nPos + 1 );
464 	rSave.pFmt = pFmt;
465 	rSave.pObj = 0;
466 }
467 
468 SwUndoDrawUnGroupConnectToLayout::SwUndoDrawUnGroupConnectToLayout()
469     : SwUndo( UNDO_DRAWUNGROUP )
470 {
471 }
472 
473 SwUndoDrawUnGroupConnectToLayout::~SwUndoDrawUnGroupConnectToLayout()
474 {
475 }
476 
477 void
478 SwUndoDrawUnGroupConnectToLayout::UndoImpl(::sw::UndoRedoContext &)
479 {
480     for ( std::vector< SdrObject >::size_type i = 0;
481           i < aDrawFmtsAndObjs.size(); ++i )
482     {
483         SdrObject* pObj( aDrawFmtsAndObjs[i].second );
484         SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(pObj->GetUserCall()) );
485         ASSERT( pDrawContact,
486                 "<SwUndoDrawUnGroupConnectToLayout::Undo(..)> -- missing SwDrawContact instance" );
487         if ( pDrawContact )
488         {
489             // deletion of instance <pDrawContact> and thus disconnection from
490             // the Writer layout.
491             pDrawContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
492             pObj->SetUserCall( 0 );
493         }
494     }
495 }
496 
497 void
498 SwUndoDrawUnGroupConnectToLayout::RedoImpl(::sw::UndoRedoContext &)
499 {
500     for ( std::vector< std::pair< SwDrawFrmFmt*, SdrObject* > >::size_type i = 0;
501           i < aDrawFmtsAndObjs.size(); ++i )
502     {
503         SwDrawFrmFmt* pFmt( aDrawFmtsAndObjs[i].first );
504         SdrObject* pObj( aDrawFmtsAndObjs[i].second );
505         SwDrawContact *pContact = new SwDrawContact( pFmt, pObj );
506         pContact->ConnectToLayout();
507         pContact->MoveObjToVisibleLayer( pObj );
508     }
509 }
510 
511 void SwUndoDrawUnGroupConnectToLayout::AddFmtAndObj( SwDrawFrmFmt* pDrawFrmFmt,
512                                                      SdrObject* pDrawObject )
513 {
514     aDrawFmtsAndObjs.push_back(
515             std::pair< SwDrawFrmFmt*, SdrObject* >( pDrawFrmFmt, pDrawObject ) );
516 }
517 
518 //-------------------------------------
519 
520 SwUndoDrawDelete::SwUndoDrawDelete( sal_uInt16 nCnt )
521 	: SwUndo( UNDO_DRAWDELETE ), nSize( nCnt ), bDelFmt( sal_True )
522 {
523 	pObjArr = new SwUndoGroupObjImpl[ nSize ];
524 	pMarkLst = new SdrMarkList();
525 }
526 
527 SwUndoDrawDelete::~SwUndoDrawDelete()
528 {
529 	if( bDelFmt )
530 	{
531 		SwUndoGroupObjImpl* pTmp = pObjArr;
532 		for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n, ++pTmp )
533 			delete pTmp->pFmt;
534 	}
535 	delete [] pObjArr;
536 	delete pMarkLst;
537 }
538 
539 void SwUndoDrawDelete::UndoImpl(::sw::UndoRedoContext & rContext)
540 {
541 	bDelFmt = sal_False;
542     SwSpzFrmFmts & rFlyFmts = *rContext.GetDoc().GetSpzFrmFmts();
543 	for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n )
544 	{
545 		SwUndoGroupObjImpl& rSave = *( pObjArr + n );
546 		::lcl_RestoreAnchor( rSave.pFmt, rSave.nNodeIdx );
547 		rFlyFmts.Insert( rSave.pFmt, rFlyFmts.Count() );
548 		SdrObject *pObj = rSave.pObj;
549 		SwDrawContact *pContact = new SwDrawContact( rSave.pFmt, pObj );
550 		pContact->_Changed( *pObj, SDRUSERCALL_INSERTED, NULL );
551         // #i45718# - follow-up of #i35635# move object to visible layer
552         pContact->MoveObjToVisibleLayer( pObj );
553         // #i45952# - notify that position attributes are already set
554         ASSERT( rSave.pFmt->ISA(SwDrawFrmFmt),
555                 "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for drawing object" );
556         if ( rSave.pFmt->ISA(SwDrawFrmFmt) )
557         {
558             static_cast<SwDrawFrmFmt*>(rSave.pFmt)->PosAttrSet();
559         }
560         // <--
561     }
562     rContext.SetSelections(0, pMarkLst);
563 }
564 
565 void SwUndoDrawDelete::RedoImpl(::sw::UndoRedoContext & rContext)
566 {
567 	bDelFmt = sal_True;
568     SwSpzFrmFmts & rFlyFmts = *rContext.GetDoc().GetSpzFrmFmts();
569 	for( sal_uInt16 n = 0; n < pMarkLst->GetMarkCount(); ++n )
570 	{
571 		SwUndoGroupObjImpl& rSave = *( pObjArr + n );
572 		SdrObject *pObj = rSave.pObj;
573 		SwDrawContact *pContact = (SwDrawContact*)GetUserCall(pObj);
574 		SwDrawFrmFmt *pFmt = (SwDrawFrmFmt*)pContact->GetFmt();
575 
576 		// object will destroy itself
577 		pContact->Changed( *pObj, SDRUSERCALL_DELETE, pObj->GetLastBoundRect() );
578 		pObj->SetUserCall( 0 );
579 
580        	// notify UNO objects to decouple
581 		::lcl_SendRemoveToUno( *pFmt );
582 
583 		rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
584 		::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
585 	}
586 }
587 
588 void SwUndoDrawDelete::AddObj( sal_uInt16 , SwDrawFrmFmt* pFmt,
589 								const SdrMark& rMark )
590 {
591 	SwUndoGroupObjImpl& rSave = *( pObjArr + pMarkLst->GetMarkCount() );
592 	rSave.pObj = rMark.GetMarkedSdrObj();
593 	rSave.pFmt = pFmt;
594 	::lcl_SaveAnchor( pFmt, rSave.nNodeIdx );
595 
596    	// notify UNO objects to decouple
597 	::lcl_SendRemoveToUno( *pFmt );
598 
599 	// remove from array
600 	SwDoc* pDoc = pFmt->GetDoc();
601 	SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts();
602 	rFlyFmts.Remove( rFlyFmts.GetPos( pFmt ));
603 
604 	pMarkLst->InsertEntry( rMark );
605 }
606 
607