Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <svl/itemiter.hxx>
21 : #include <hintids.hxx>
22 : #include <hints.hxx>
23 : #include <fmtflcnt.hxx>
24 : #include <fmtanchr.hxx>
25 : #include <fmtcntnt.hxx>
26 : #include <txtflcnt.hxx>
27 : #include <frmfmt.hxx>
28 : #include <flyfrm.hxx>
29 : #include <UndoCore.hxx>
30 : #include <UndoDraw.hxx>
31 : #include <rolbck.hxx>
32 : #include <doc.hxx>
33 : #include <docary.hxx>
34 : #include <rootfrm.hxx>
35 : #include <swundo.hxx>
36 : #include <pam.hxx>
37 : #include <ndtxt.hxx>
38 : // OD 26.06.2003 #108784#
39 : #include <dcontact.hxx>
40 : #include <ndole.hxx>
41 :
42 0 : SwUndoFlyBase::SwUndoFlyBase( SwFrmFmt* pFormat, SwUndoId nUndoId )
43 0 : : SwUndo( nUndoId ), pFrmFmt( pFormat )
44 : {
45 0 : }
46 :
47 0 : SwUndoFlyBase::~SwUndoFlyBase()
48 : {
49 0 : if( bDelFmt ) // delete during an Undo?
50 0 : delete pFrmFmt;
51 0 : }
52 :
53 0 : void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrm)
54 : {
55 0 : SwDoc *const pDoc = & rContext.GetDoc();
56 :
57 : // add again into array
58 0 : SwFrmFmts& rFlyFmts = *(SwFrmFmts*)pDoc->GetSpzFrmFmts();
59 0 : rFlyFmts.push_back( pFrmFmt );
60 :
61 : // OD 26.06.2003 #108784# - insert 'master' drawing object into drawing page
62 0 : if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
63 : {
64 : SwDrawContact* pDrawContact =
65 0 : static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
66 0 : if ( pDrawContact )
67 : {
68 0 : pDrawContact->InsertMasterIntoDrawPage();
69 : // #i40845# - follow-up of #i35635#
70 : // move object to visible layer
71 0 : pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() );
72 : }
73 : }
74 :
75 0 : SwFmtAnchor aAnchor( (RndStdIds)nRndId );
76 :
77 0 : if (FLY_AT_PAGE == nRndId)
78 : {
79 0 : aAnchor.SetPageNum( (sal_uInt16)nNdPgPos );
80 : }
81 : else
82 : {
83 0 : SwPosition aNewPos(pDoc->GetNodes().GetEndOfContent());
84 0 : aNewPos.nNode = nNdPgPos;
85 0 : if ((FLY_AS_CHAR == nRndId) || (FLY_AT_CHAR == nRndId))
86 : {
87 0 : aNewPos.nContent.Assign( aNewPos.nNode.GetNode().GetCntntNode(),
88 0 : nCntPos );
89 : }
90 0 : aAnchor.SetAnchor( &aNewPos );
91 : }
92 :
93 0 : pFrmFmt->SetFmtAttr( aAnchor ); // reset anchor
94 :
95 0 : if( RES_DRAWFRMFMT != pFrmFmt->Which() )
96 : {
97 : // get Content and reset ContentAttribute
98 0 : SwNodeIndex aIdx( pDoc->GetNodes() );
99 0 : RestoreSection( pDoc, &aIdx, SwFlyStartNode );
100 0 : pFrmFmt->SetFmtAttr( SwFmtCntnt( aIdx.GetNode().GetStartNode() ));
101 : }
102 :
103 : // Set InCntntAttribute not until there is content!
104 : // Otherwise the layout would format the Fly beforehand but would not find
105 : // content; this happened with graphics from the internet.
106 0 : if (FLY_AS_CHAR == nRndId)
107 : {
108 : // there must be at least the attribute in a TextNode
109 0 : SwCntntNode* pCNd = aAnchor.GetCntntAnchor()->nNode.GetNode().GetCntntNode();
110 : OSL_ENSURE( pCNd->IsTxtNode(), "no Text Node at position." );
111 0 : SwFmtFlyCnt aFmt( pFrmFmt );
112 0 : static_cast<SwTxtNode*>(pCNd)->InsertItem( aFmt, nCntPos, nCntPos );
113 : }
114 :
115 0 : pFrmFmt->MakeFrms();
116 :
117 0 : if( bShowSelFrm )
118 : {
119 0 : rContext.SetSelections(pFrmFmt, 0);
120 : }
121 :
122 0 : if( GetHistory() )
123 0 : GetHistory()->Rollback( pDoc );
124 :
125 0 : switch( nRndId )
126 : {
127 : case FLY_AS_CHAR:
128 : case FLY_AT_CHAR:
129 : {
130 0 : const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
131 0 : nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
132 0 : nCntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex();
133 : }
134 0 : break;
135 : case FLY_AT_PARA:
136 : case FLY_AT_FLY:
137 : {
138 0 : const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
139 0 : nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
140 : }
141 0 : break;
142 : case FLY_AT_PAGE:
143 0 : break;
144 : }
145 0 : bDelFmt = false;
146 0 : }
147 :
148 0 : void SwUndoFlyBase::DelFly( SwDoc* pDoc )
149 : {
150 0 : bDelFmt = true; // delete Format in DTOR
151 0 : pFrmFmt->DelFrms(); // destroy Frms
152 :
153 : // all Uno objects should now log themselves off
154 : {
155 0 : SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFrmFmt );
156 0 : pFrmFmt->ModifyNotification( &aMsgHint, &aMsgHint );
157 : }
158 :
159 0 : if ( RES_DRAWFRMFMT != pFrmFmt->Which() )
160 : {
161 : // if there is content than save it
162 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
163 : OSL_ENSURE( rCntnt.GetCntntIdx(), "Fly ohne Inhalt" );
164 :
165 0 : SaveSection( pDoc, *rCntnt.GetCntntIdx() );
166 0 : ((SwFmtCntnt&)rCntnt).SetNewCntntIdx( (const SwNodeIndex*)0 );
167 : }
168 : // OD 02.07.2003 #108784# - remove 'master' drawing object from drawing page
169 0 : else if ( RES_DRAWFRMFMT == pFrmFmt->Which() )
170 : {
171 : SwDrawContact* pDrawContact =
172 0 : static_cast<SwDrawContact*>(pFrmFmt->FindContactObj());
173 0 : if ( pDrawContact )
174 : {
175 0 : pDrawContact->RemoveMasterFromDrawPage();
176 : }
177 : }
178 :
179 0 : const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
180 0 : const SwPosition* pPos = rAnchor.GetCntntAnchor();
181 : // The positions in Nodes array got shifted.
182 0 : nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
183 0 : if (FLY_AS_CHAR == nRndId)
184 : {
185 0 : nNdPgPos = pPos->nNode.GetIndex();
186 0 : nCntPos = pPos->nContent.GetIndex();
187 0 : SwTxtNode *const pTxtNd = pPos->nNode.GetNode().GetTxtNode();
188 : OSL_ENSURE( pTxtNd, "Kein Textnode gefunden" );
189 : SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
190 0 : pTxtNd->GetTxtAttrForCharAt( nCntPos, RES_TXTATR_FLYCNT ) );
191 : // attribute is still in TextNode, delete
192 0 : if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFrmFmt )
193 : {
194 : // Pointer to 0, do not delete
195 0 : ((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt();
196 0 : SwIndex aIdx( pPos->nContent );
197 0 : pTxtNd->EraseText( aIdx, 1 );
198 : }
199 : }
200 0 : else if (FLY_AT_CHAR == nRndId)
201 : {
202 0 : nNdPgPos = pPos->nNode.GetIndex();
203 0 : nCntPos = pPos->nContent.GetIndex();
204 : }
205 0 : else if ((FLY_AT_PARA == nRndId) || (FLY_AT_FLY == nRndId))
206 : {
207 0 : nNdPgPos = pPos->nNode.GetIndex();
208 : }
209 : else
210 : {
211 0 : nNdPgPos = rAnchor.GetPageNum();
212 : }
213 :
214 0 : pFrmFmt->ResetFmtAttr( RES_ANCHOR ); // delete anchor
215 :
216 : // delete from array
217 0 : SwFrmFmts& rFlyFmts = *(SwFrmFmts*)pDoc->GetSpzFrmFmts();
218 0 : rFlyFmts.erase( std::find( rFlyFmts.begin(), rFlyFmts.end(), pFrmFmt ));
219 0 : }
220 :
221 0 : SwUndoInsLayFmt::SwUndoInsLayFmt( SwFrmFmt* pFormat, sal_uLong nNodeIdx, sal_Int32 nCntIdx )
222 0 : : SwUndoFlyBase( pFormat, RES_DRAWFRMFMT == pFormat->Which() ?
223 : UNDO_INSDRAWFMT : UNDO_INSLAYFMT ),
224 0 : mnCrsrSaveIndexPara( nNodeIdx ), mnCrsrSaveIndexPos( nCntIdx )
225 : {
226 0 : const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
227 0 : nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
228 0 : bDelFmt = false;
229 0 : switch( nRndId )
230 : {
231 : case FLY_AT_PAGE:
232 0 : nNdPgPos = rAnchor.GetPageNum();
233 0 : break;
234 : case FLY_AT_PARA:
235 : case FLY_AT_FLY:
236 0 : nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
237 0 : break;
238 : case FLY_AS_CHAR:
239 : case FLY_AT_CHAR:
240 : {
241 0 : const SwPosition* pPos = rAnchor.GetCntntAnchor();
242 0 : nCntPos = pPos->nContent.GetIndex();
243 0 : nNdPgPos = pPos->nNode.GetIndex();
244 : }
245 0 : break;
246 : default:
247 : OSL_FAIL( "Which FlyFrame?" );
248 : }
249 0 : }
250 :
251 0 : SwUndoInsLayFmt::~SwUndoInsLayFmt()
252 : {
253 0 : }
254 :
255 0 : void SwUndoInsLayFmt::UndoImpl(::sw::UndoRedoContext & rContext)
256 : {
257 0 : SwDoc & rDoc(rContext.GetDoc());
258 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
259 0 : if( rCntnt.GetCntntIdx() ) // no content
260 : {
261 0 : bool bRemoveIdx = true;
262 0 : if( mnCrsrSaveIndexPara > 0 )
263 : {
264 : SwTxtNode *const pNode =
265 0 : rDoc.GetNodes()[mnCrsrSaveIndexPara]->GetTxtNode();
266 0 : if( pNode )
267 : {
268 0 : SwNodeIndex aIdx( rDoc.GetNodes(),
269 0 : rCntnt.GetCntntIdx()->GetIndex() );
270 0 : SwNodeIndex aEndIdx( rDoc.GetNodes(),
271 0 : aIdx.GetNode().EndOfSectionIndex() );
272 0 : SwIndex aIndex( pNode, mnCrsrSaveIndexPos );
273 0 : SwPosition aPos( *pNode, aIndex );
274 0 : rDoc.CorrAbs( aIdx, aEndIdx, aPos, sal_True );
275 0 : bRemoveIdx = false;
276 : }
277 : }
278 0 : if( bRemoveIdx )
279 : {
280 0 : RemoveIdxFromSection( rDoc, rCntnt.GetCntntIdx()->GetIndex() );
281 : }
282 : }
283 0 : DelFly(& rDoc);
284 0 : }
285 :
286 0 : void SwUndoInsLayFmt::RedoImpl(::sw::UndoRedoContext & rContext)
287 : {
288 0 : InsFly(rContext);
289 0 : }
290 :
291 0 : void SwUndoInsLayFmt::RepeatImpl(::sw::RepeatContext & rContext)
292 : {
293 0 : SwDoc *const pDoc = & rContext.GetDoc();
294 : // get anchor and reset it
295 0 : SwFmtAnchor aAnchor( pFrmFmt->GetAnchor() );
296 0 : if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
297 0 : (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
298 0 : (FLY_AS_CHAR == aAnchor.GetAnchorId()))
299 : {
300 0 : SwPosition aPos( *rContext.GetRepeatPaM().GetPoint() );
301 0 : if (FLY_AT_PARA == aAnchor.GetAnchorId())
302 : {
303 0 : aPos.nContent.Assign( 0, 0 );
304 : }
305 0 : aAnchor.SetAnchor( &aPos );
306 : }
307 0 : else if( FLY_AT_FLY == aAnchor.GetAnchorId() )
308 : {
309 : SwStartNode const*const pSttNd =
310 0 : rContext.GetRepeatPaM().GetNode()->FindFlyStartNode();
311 0 : if( pSttNd )
312 : {
313 0 : SwPosition aPos( *pSttNd );
314 0 : aAnchor.SetAnchor( &aPos );
315 : }
316 : else
317 : {
318 0 : return ;
319 : }
320 : }
321 0 : else if (FLY_AT_PAGE == aAnchor.GetAnchorId())
322 : {
323 0 : aAnchor.SetPageNum( pDoc->GetCurrentLayout()->GetCurrPage( &rContext.GetRepeatPaM() ));
324 : }
325 : else {
326 : OSL_FAIL( "What kind of anchor is this?" );
327 : }
328 :
329 0 : SwFrmFmt* pFlyFmt = pDoc->CopyLayoutFmt( *pFrmFmt, aAnchor, true, true );
330 0 : (void) pFlyFmt;
331 : }
332 :
333 : // #111827#
334 0 : OUString SwUndoInsLayFmt::GetComment() const
335 : {
336 0 : OUString aResult;
337 :
338 : // HACK: disable caching:
339 : // the SfxUndoManager calls GetComment() too early: the pFrmFmt does not
340 : // have a SwDrawContact yet, so it will fall back to SwUndo::GetComment(),
341 : // which sets pComment to a wrong value.
342 : // if (! pComment)
343 : if (true)
344 : {
345 : /*
346 : If frame format is present and has an SdrObject use the undo
347 : comment of the SdrObject. Otherwise use the default comment.
348 : */
349 0 : bool bDone = false;
350 0 : if (pFrmFmt)
351 : {
352 0 : const SdrObject * pSdrObj = pFrmFmt->FindSdrObject();
353 0 : if ( pSdrObj )
354 : {
355 0 : aResult = SdrUndoNewObj::GetComment( *pSdrObj );
356 0 : bDone = true;
357 : }
358 : }
359 :
360 0 : if (! bDone)
361 0 : aResult = SwUndo::GetComment();
362 : }
363 : else
364 : aResult = *pComment;
365 :
366 0 : return aResult;
367 : }
368 :
369 : static SwUndoId
370 0 : lcl_GetSwUndoId(SwFrmFmt *const pFrmFmt)
371 : {
372 0 : if (RES_DRAWFRMFMT != pFrmFmt->Which())
373 : {
374 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
375 : OSL_ENSURE( rCntnt.GetCntntIdx(), "Fly without content" );
376 :
377 0 : SwNodeIndex firstNode(*rCntnt.GetCntntIdx(), 1);
378 0 : SwNoTxtNode *const pNoTxtNode(firstNode.GetNode().GetNoTxtNode());
379 0 : if (pNoTxtNode && pNoTxtNode->IsGrfNode())
380 : {
381 0 : return UNDO_DELGRF;
382 : }
383 0 : else if (pNoTxtNode && pNoTxtNode->IsOLENode())
384 : {
385 : // surprisingly not UNDO_DELOLE, which does not seem to work
386 0 : return UNDO_DELETE;
387 0 : }
388 : }
389 0 : return UNDO_DELLAYFMT;
390 : }
391 :
392 0 : SwUndoDelLayFmt::SwUndoDelLayFmt( SwFrmFmt* pFormat )
393 : : SwUndoFlyBase( pFormat, lcl_GetSwUndoId(pFormat) )
394 0 : , bShowSelFrm( true )
395 : {
396 0 : SwDoc* pDoc = pFormat->GetDoc();
397 0 : DelFly( pDoc );
398 0 : }
399 :
400 0 : SwRewriter SwUndoDelLayFmt::GetRewriter() const
401 : {
402 0 : SwRewriter aRewriter;
403 :
404 0 : SwDoc * pDoc = pFrmFmt->GetDoc();
405 :
406 0 : if (pDoc)
407 : {
408 0 : SwNodeIndex* pIdx = GetMvSttIdx();
409 0 : if( 1 == GetMvNodeCnt() && pIdx)
410 : {
411 0 : SwNode *const pNd = & pIdx->GetNode();
412 :
413 0 : if ( pNd->IsNoTxtNode() && pNd->IsOLENode())
414 : {
415 0 : SwOLENode * pOLENd = pNd->GetOLENode();
416 :
417 0 : aRewriter.AddRule(UndoArg1, pOLENd->GetDescription());
418 : }
419 : }
420 : }
421 :
422 0 : return aRewriter;
423 : }
424 :
425 0 : void SwUndoDelLayFmt::UndoImpl(::sw::UndoRedoContext & rContext)
426 : {
427 0 : InsFly( rContext, bShowSelFrm );
428 0 : }
429 :
430 0 : void SwUndoDelLayFmt::RedoImpl(::sw::UndoRedoContext & rContext)
431 : {
432 0 : SwDoc & rDoc(rContext.GetDoc());
433 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
434 0 : if( rCntnt.GetCntntIdx() ) // no content
435 : {
436 0 : RemoveIdxFromSection(rDoc, rCntnt.GetCntntIdx()->GetIndex());
437 : }
438 :
439 0 : DelFly(& rDoc);
440 0 : }
441 :
442 0 : void SwUndoDelLayFmt::RedoForRollback()
443 : {
444 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
445 0 : if( rCntnt.GetCntntIdx() ) // no content
446 0 : RemoveIdxFromSection( *pFrmFmt->GetDoc(),
447 0 : rCntnt.GetCntntIdx()->GetIndex() );
448 :
449 0 : DelFly( pFrmFmt->GetDoc() );
450 0 : }
451 :
452 0 : SwUndoSetFlyFmt::SwUndoSetFlyFmt( SwFrmFmt& rFlyFmt, SwFrmFmt& rNewFrmFmt )
453 : : SwUndo( UNDO_SETFLYFRMFMT ), SwClient( &rFlyFmt ), pFrmFmt( &rFlyFmt ),
454 0 : pOldFmt( (SwFrmFmt*)rFlyFmt.DerivedFrom() ), pNewFmt( &rNewFrmFmt ),
455 0 : pItemSet( new SfxItemSet( *rFlyFmt.GetAttrSet().GetPool(),
456 0 : rFlyFmt.GetAttrSet().GetRanges() )),
457 : nOldNode( 0 ), nNewNode( 0 ),
458 : nOldCntnt( 0 ), nNewCntnt( 0 ),
459 0 : nOldAnchorTyp( 0 ), nNewAnchorTyp( 0 ), bAnchorChgd( false )
460 : {
461 0 : }
462 :
463 0 : SwRewriter SwUndoSetFlyFmt::GetRewriter() const
464 : {
465 0 : SwRewriter aRewriter;
466 :
467 0 : if (pNewFmt)
468 0 : aRewriter.AddRule(UndoArg1, pNewFmt->GetName());
469 :
470 0 : return aRewriter;
471 : }
472 :
473 0 : SwUndoSetFlyFmt::~SwUndoSetFlyFmt()
474 : {
475 0 : delete pItemSet;
476 0 : }
477 :
478 0 : void SwUndoSetFlyFmt::DeRegisterFromFormat( SwFmt& rFmt )
479 : {
480 0 : rFmt.Remove(this);
481 0 : }
482 :
483 0 : void SwUndoSetFlyFmt::GetAnchor( SwFmtAnchor& rAnchor,
484 : sal_uLong nNode, sal_Int32 nCntnt )
485 : {
486 0 : RndStdIds nAnchorTyp = rAnchor.GetAnchorId();
487 0 : if (FLY_AT_PAGE != nAnchorTyp)
488 : {
489 0 : SwNode* pNd = pFrmFmt->GetDoc()->GetNodes()[ nNode ];
490 :
491 0 : if( FLY_AT_FLY == nAnchorTyp
492 0 : ? ( !pNd->IsStartNode() || SwFlyStartNode !=
493 0 : ((SwStartNode*)pNd)->GetStartNodeType() )
494 0 : : !pNd->IsTxtNode() )
495 : {
496 0 : pNd = 0; // invalid position
497 : }
498 : else
499 : {
500 0 : SwPosition aPos( *pNd );
501 0 : if ((FLY_AS_CHAR == nAnchorTyp) ||
502 : (FLY_AT_CHAR == nAnchorTyp))
503 : {
504 0 : if (nCntnt > static_cast<SwTxtNode*>(pNd)->GetTxt().getLength())
505 : {
506 0 : pNd = 0; // invalid position
507 : }
508 : else
509 : {
510 0 : aPos.nContent.Assign(static_cast<SwTxtNode*>(pNd), nCntnt);
511 : }
512 : }
513 0 : if ( pNd )
514 : {
515 0 : rAnchor.SetAnchor( &aPos );
516 0 : }
517 : }
518 :
519 0 : if( !pNd )
520 : {
521 : // invalid position - assign first page
522 0 : rAnchor.SetType( FLY_AT_PAGE );
523 0 : rAnchor.SetPageNum( 1 );
524 : }
525 : }
526 : else
527 0 : rAnchor.SetPageNum( nCntnt );
528 0 : }
529 :
530 0 : void SwUndoSetFlyFmt::UndoImpl(::sw::UndoRedoContext & rContext)
531 : {
532 0 : SwDoc & rDoc = rContext.GetDoc();
533 :
534 : // Is the new Format still existent?
535 0 : if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmt*)pOldFmt ) )
536 : {
537 0 : if( bAnchorChgd )
538 0 : pFrmFmt->DelFrms();
539 :
540 0 : if( pFrmFmt->DerivedFrom() != pOldFmt )
541 0 : pFrmFmt->SetDerivedFrom( pOldFmt );
542 :
543 0 : SfxItemIter aIter( *pItemSet );
544 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
545 0 : while( pItem )
546 : {
547 0 : if( IsInvalidItem( pItem ))
548 : pFrmFmt->ResetFmtAttr( pItemSet->GetWhichByPos(
549 0 : aIter.GetCurPos() ));
550 : else
551 0 : pFrmFmt->SetFmtAttr( *pItem );
552 :
553 0 : if( aIter.IsAtEnd() )
554 0 : break;
555 0 : pItem = aIter.NextItem();
556 : }
557 :
558 0 : if( bAnchorChgd )
559 : {
560 0 : const SwFmtAnchor& rOldAnch = pFrmFmt->GetAnchor();
561 0 : if (FLY_AS_CHAR == rOldAnch.GetAnchorId())
562 : {
563 : // With InCntnts it's tricky: the text attribute needs to be
564 : // deleted. Unfortunately, this not only destroys the Frms but
565 : // also the format. To prevent that, first detach the
566 : // connection between attribute and format.
567 0 : const SwPosition *pPos = rOldAnch.GetCntntAnchor();
568 0 : SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
569 : OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
570 0 : const sal_Int32 nIdx = pPos->nContent.GetIndex();
571 : SwTxtAttr * pHnt = pTxtNode->GetTxtAttrForCharAt(
572 0 : nIdx, RES_TXTATR_FLYCNT );
573 : OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
574 : "Missing FlyInCnt-Hint." );
575 : OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt,
576 : "Wrong TxtFlyCnt-Hint." );
577 0 : const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
578 :
579 : // Connection is now detached, therefore the attribute can be
580 : // deleted
581 0 : pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
582 : }
583 :
584 : // reposition anchor
585 0 : SwFmtAnchor aNewAnchor( (RndStdIds) nOldAnchorTyp );
586 0 : GetAnchor( aNewAnchor, nOldNode, nOldCntnt );
587 0 : pFrmFmt->SetFmtAttr( aNewAnchor );
588 :
589 0 : if (FLY_AS_CHAR == aNewAnchor.GetAnchorId())
590 : {
591 0 : SwPosition* pPos = (SwPosition*)aNewAnchor.GetCntntAnchor();
592 0 : SwFmtFlyCnt aFmt( pFrmFmt );
593 0 : pPos->nNode.GetNode().GetTxtNode()->InsertItem( aFmt,
594 0 : nOldCntnt, 0 );
595 : }
596 :
597 0 : pFrmFmt->MakeFrms();
598 : }
599 0 : rContext.SetSelections(pFrmFmt, 0);
600 : }
601 0 : }
602 :
603 0 : void SwUndoSetFlyFmt::RedoImpl(::sw::UndoRedoContext & rContext)
604 : {
605 0 : SwDoc & rDoc = rContext.GetDoc();
606 :
607 : // Is the new Format still existent?
608 0 : if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmt*)pNewFmt ) )
609 : {
610 :
611 0 : if( bAnchorChgd )
612 : {
613 0 : SwFmtAnchor aNewAnchor( (RndStdIds) nNewAnchorTyp );
614 0 : GetAnchor( aNewAnchor, nNewNode, nNewCntnt );
615 0 : SfxItemSet aSet( rDoc.GetAttrPool(), aFrmFmtSetRange );
616 0 : aSet.Put( aNewAnchor );
617 0 : rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, &aSet );
618 : }
619 : else
620 0 : rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, 0 );
621 :
622 0 : rContext.SetSelections(pFrmFmt, 0);
623 : }
624 0 : }
625 :
626 0 : void SwUndoSetFlyFmt::PutAttr( sal_uInt16 nWhich, const SfxPoolItem* pItem )
627 : {
628 0 : if( pItem && pItem != GetDfltAttr( nWhich ) )
629 : {
630 : // Special treatment for this anchor
631 0 : if( RES_ANCHOR == nWhich )
632 : {
633 : // only keep the first change
634 : OSL_ENSURE( !bAnchorChgd, "multiple changes of an anchor are not allowed!" );
635 :
636 0 : bAnchorChgd = true;
637 :
638 0 : const SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
639 0 : switch( nOldAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
640 : {
641 : case FLY_AS_CHAR:
642 : case FLY_AT_CHAR:
643 0 : nOldCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
644 : case FLY_AT_PARA:
645 : case FLY_AT_FLY:
646 0 : nOldNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
647 0 : break;
648 :
649 : default:
650 0 : nOldCntnt = pAnchor->GetPageNum();
651 : }
652 :
653 0 : pAnchor = (SwFmtAnchor*)&pFrmFmt->GetAnchor();
654 0 : switch( nNewAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
655 : {
656 : case FLY_AS_CHAR:
657 : case FLY_AT_CHAR:
658 0 : nNewCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
659 : case FLY_AT_PARA:
660 : case FLY_AT_FLY:
661 0 : nNewNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
662 0 : break;
663 :
664 : default:
665 0 : nNewCntnt = pAnchor->GetPageNum();
666 : }
667 : }
668 : else
669 0 : pItemSet->Put( *pItem );
670 : }
671 : else
672 0 : pItemSet->InvalidateItem( nWhich );
673 0 : }
674 :
675 0 : void SwUndoSetFlyFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* )
676 : {
677 0 : if( pOld )
678 : {
679 0 : sal_uInt16 nWhich = pOld->Which();
680 :
681 0 : if( nWhich < POOLATTR_END )
682 0 : PutAttr( nWhich, pOld );
683 0 : else if( RES_ATTRSET_CHG == nWhich )
684 : {
685 0 : SfxItemIter aIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
686 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
687 0 : while( pItem )
688 : {
689 0 : PutAttr( pItem->Which(), pItem );
690 0 : if( aIter.IsAtEnd() )
691 0 : break;
692 0 : pItem = aIter.NextItem();
693 0 : }
694 : }
695 : }
696 0 : }
697 :
698 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|