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