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 happend 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 = sal_False;
146 0 : }
147 :
148 0 : void SwUndoFlyBase::DelFly( SwDoc* pDoc )
149 : {
150 0 : bDelFmt = sal_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 :
217 : // delete from array
218 0 : SwFrmFmts& rFlyFmts = *(SwFrmFmts*)pDoc->GetSpzFrmFmts();
219 0 : rFlyFmts.erase( std::find( rFlyFmts.begin(), rFlyFmts.end(), pFrmFmt ));
220 0 : }
221 :
222 0 : SwUndoInsLayFmt::SwUndoInsLayFmt( SwFrmFmt* pFormat, sal_uLong nNodeIdx, xub_StrLen nCntIdx )
223 0 : : SwUndoFlyBase( pFormat, RES_DRAWFRMFMT == pFormat->Which() ?
224 : UNDO_INSDRAWFMT : UNDO_INSLAYFMT ),
225 0 : mnCrsrSaveIndexPara( nNodeIdx ), mnCrsrSaveIndexPos( nCntIdx )
226 : {
227 0 : const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
228 0 : nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
229 0 : bDelFmt = sal_False;
230 0 : switch( nRndId )
231 : {
232 : case FLY_AT_PAGE:
233 0 : nNdPgPos = rAnchor.GetPageNum();
234 0 : break;
235 : case FLY_AT_PARA:
236 : case FLY_AT_FLY:
237 0 : nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex();
238 0 : break;
239 : case FLY_AS_CHAR:
240 : case FLY_AT_CHAR:
241 : {
242 0 : const SwPosition* pPos = rAnchor.GetCntntAnchor();
243 0 : nCntPos = pPos->nContent.GetIndex();
244 0 : nNdPgPos = pPos->nNode.GetIndex();
245 : }
246 0 : break;
247 : default:
248 : OSL_FAIL( "Which FlyFrame?" );
249 : }
250 0 : }
251 :
252 0 : SwUndoInsLayFmt::~SwUndoInsLayFmt()
253 : {
254 0 : }
255 :
256 0 : void SwUndoInsLayFmt::UndoImpl(::sw::UndoRedoContext & rContext)
257 : {
258 0 : SwDoc & rDoc(rContext.GetDoc());
259 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
260 0 : if( rCntnt.GetCntntIdx() ) // no content
261 : {
262 0 : bool bRemoveIdx = true;
263 0 : if( mnCrsrSaveIndexPara > 0 )
264 : {
265 : SwTxtNode *const pNode =
266 0 : rDoc.GetNodes()[mnCrsrSaveIndexPara]->GetTxtNode();
267 0 : if( pNode )
268 : {
269 0 : SwNodeIndex aIdx( rDoc.GetNodes(),
270 0 : rCntnt.GetCntntIdx()->GetIndex() );
271 0 : SwNodeIndex aEndIdx( rDoc.GetNodes(),
272 0 : aIdx.GetNode().EndOfSectionIndex() );
273 0 : SwIndex aIndex( pNode, mnCrsrSaveIndexPos );
274 0 : SwPosition aPos( *pNode, aIndex );
275 0 : rDoc.CorrAbs( aIdx, aEndIdx, aPos, sal_True );
276 0 : bRemoveIdx = false;
277 : }
278 : }
279 0 : if( bRemoveIdx )
280 : {
281 0 : RemoveIdxFromSection( rDoc, rCntnt.GetCntntIdx()->GetIndex() );
282 : }
283 : }
284 0 : DelFly(& rDoc);
285 0 : }
286 :
287 0 : void SwUndoInsLayFmt::RedoImpl(::sw::UndoRedoContext & rContext)
288 : {
289 0 : InsFly(rContext);
290 0 : }
291 :
292 0 : void SwUndoInsLayFmt::RepeatImpl(::sw::RepeatContext & rContext)
293 : {
294 0 : SwDoc *const pDoc = & rContext.GetDoc();
295 : // get anchor and reset it
296 0 : SwFmtAnchor aAnchor( pFrmFmt->GetAnchor() );
297 0 : if ((FLY_AT_PARA == aAnchor.GetAnchorId()) ||
298 0 : (FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
299 0 : (FLY_AS_CHAR == aAnchor.GetAnchorId()))
300 : {
301 0 : SwPosition aPos( *rContext.GetRepeatPaM().GetPoint() );
302 0 : if (FLY_AT_PARA == aAnchor.GetAnchorId())
303 : {
304 0 : aPos.nContent.Assign( 0, 0 );
305 : }
306 0 : aAnchor.SetAnchor( &aPos );
307 : }
308 0 : else if( FLY_AT_FLY == aAnchor.GetAnchorId() )
309 : {
310 : SwStartNode const*const pSttNd =
311 0 : rContext.GetRepeatPaM().GetNode()->FindFlyStartNode();
312 0 : if( pSttNd )
313 : {
314 0 : SwPosition aPos( *pSttNd );
315 0 : aAnchor.SetAnchor( &aPos );
316 : }
317 : else
318 : {
319 0 : return ;
320 : }
321 : }
322 0 : else if (FLY_AT_PAGE == aAnchor.GetAnchorId())
323 : {
324 0 : aAnchor.SetPageNum( pDoc->GetCurrentLayout()->GetCurrPage( &rContext.GetRepeatPaM() ));
325 : }
326 : else {
327 : OSL_FAIL( "What kind of anchor is this?" );
328 : }
329 :
330 0 : SwFrmFmt* pFlyFmt = pDoc->CopyLayoutFmt( *pFrmFmt, aAnchor, true, true );
331 0 : (void) pFlyFmt;
332 : }
333 :
334 : // #111827#
335 0 : rtl::OUString SwUndoInsLayFmt::GetComment() const
336 : {
337 0 : String aResult;
338 :
339 : // HACK: disable caching:
340 : // the SfxUndoManager calls GetComment() too early: the pFrmFmt does not
341 : // have a SwDrawContact yet, so it will fall back to SwUndo::GetComment(),
342 : // which sets pComment to a wrong value.
343 : // if (! pComment)
344 : if (true)
345 : {
346 : /*
347 : If frame format is present and has an SdrObject use the undo
348 : comment of the SdrObject. Otherwise use the default comment.
349 : */
350 0 : bool bDone = false;
351 0 : if (pFrmFmt)
352 : {
353 0 : const SdrObject * pSdrObj = pFrmFmt->FindSdrObject();
354 0 : if ( pSdrObj )
355 : {
356 0 : aResult = SdrUndoNewObj::GetComment( *pSdrObj );
357 0 : bDone = true;
358 : }
359 : }
360 :
361 0 : if (! bDone)
362 0 : aResult = SwUndo::GetComment();
363 : }
364 : else
365 : aResult = *pComment;
366 :
367 0 : return aResult;
368 : }
369 :
370 : static SwUndoId
371 0 : lcl_GetSwUndoId(SwFrmFmt *const pFrmFmt)
372 : {
373 0 : if (RES_DRAWFRMFMT != pFrmFmt->Which())
374 : {
375 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
376 : OSL_ENSURE( rCntnt.GetCntntIdx(), "Fly without content" );
377 :
378 0 : SwNodeIndex firstNode(*rCntnt.GetCntntIdx(), 1);
379 0 : SwNoTxtNode *const pNoTxtNode(firstNode.GetNode().GetNoTxtNode());
380 0 : if (pNoTxtNode && pNoTxtNode->IsGrfNode())
381 : {
382 0 : return UNDO_DELGRF;
383 : }
384 0 : else if (pNoTxtNode && pNoTxtNode->IsOLENode())
385 : {
386 : // surprisingly not UNDO_DELOLE, which does not seem to work
387 0 : return UNDO_DELETE;
388 0 : }
389 : }
390 0 : return UNDO_DELLAYFMT;
391 : }
392 :
393 0 : SwUndoDelLayFmt::SwUndoDelLayFmt( SwFrmFmt* pFormat )
394 : : SwUndoFlyBase( pFormat, lcl_GetSwUndoId(pFormat) )
395 0 : , bShowSelFrm( sal_True )
396 : {
397 0 : SwDoc* pDoc = pFormat->GetDoc();
398 0 : DelFly( pDoc );
399 0 : }
400 :
401 0 : SwRewriter SwUndoDelLayFmt::GetRewriter() const
402 : {
403 0 : SwRewriter aRewriter;
404 :
405 0 : SwDoc * pDoc = pFrmFmt->GetDoc();
406 :
407 0 : if (pDoc)
408 : {
409 0 : SwNodeIndex* pIdx = GetMvSttIdx();
410 0 : if( 1 == GetMvNodeCnt() && pIdx)
411 : {
412 0 : SwNode *const pNd = & pIdx->GetNode();
413 :
414 0 : if ( pNd->IsNoTxtNode() && pNd->IsOLENode())
415 : {
416 0 : SwOLENode * pOLENd = pNd->GetOLENode();
417 :
418 0 : aRewriter.AddRule(UndoArg1, pOLENd->GetDescription());
419 : }
420 : }
421 : }
422 :
423 0 : return aRewriter;
424 : }
425 :
426 0 : void SwUndoDelLayFmt::UndoImpl(::sw::UndoRedoContext & rContext)
427 : {
428 0 : InsFly( rContext, bShowSelFrm );
429 0 : }
430 :
431 0 : void SwUndoDelLayFmt::RedoImpl(::sw::UndoRedoContext & rContext)
432 : {
433 0 : SwDoc & rDoc(rContext.GetDoc());
434 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
435 0 : if( rCntnt.GetCntntIdx() ) // no content
436 : {
437 0 : RemoveIdxFromSection(rDoc, rCntnt.GetCntntIdx()->GetIndex());
438 : }
439 :
440 0 : DelFly(& rDoc);
441 0 : }
442 :
443 0 : void SwUndoDelLayFmt::RedoForRollback()
444 : {
445 0 : const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt();
446 0 : if( rCntnt.GetCntntIdx() ) // no content
447 0 : RemoveIdxFromSection( *pFrmFmt->GetDoc(),
448 0 : rCntnt.GetCntntIdx()->GetIndex() );
449 :
450 0 : DelFly( pFrmFmt->GetDoc() );
451 0 : }
452 :
453 0 : SwUndoSetFlyFmt::SwUndoSetFlyFmt( SwFrmFmt& rFlyFmt, SwFrmFmt& rNewFrmFmt )
454 : : SwUndo( UNDO_SETFLYFRMFMT ), SwClient( &rFlyFmt ), pFrmFmt( &rFlyFmt ),
455 0 : pOldFmt( (SwFrmFmt*)rFlyFmt.DerivedFrom() ), pNewFmt( &rNewFrmFmt ),
456 0 : pItemSet( new SfxItemSet( *rFlyFmt.GetAttrSet().GetPool(),
457 0 : rFlyFmt.GetAttrSet().GetRanges() )),
458 : nOldNode( 0 ), nNewNode( 0 ),
459 : nOldCntnt( 0 ), nNewCntnt( 0 ),
460 0 : nOldAnchorTyp( 0 ), nNewAnchorTyp( 0 ), bAnchorChgd( sal_False )
461 : {
462 0 : }
463 :
464 0 : SwRewriter SwUndoSetFlyFmt::GetRewriter() const
465 : {
466 0 : SwRewriter aRewriter;
467 :
468 0 : if (pNewFmt)
469 0 : aRewriter.AddRule(UndoArg1, pNewFmt->GetName());
470 :
471 0 : return aRewriter;
472 : }
473 :
474 0 : SwUndoSetFlyFmt::~SwUndoSetFlyFmt()
475 : {
476 0 : delete pItemSet;
477 0 : }
478 :
479 0 : void SwUndoSetFlyFmt::DeRegisterFromFormat( SwFmt& rFmt )
480 : {
481 0 : rFmt.Remove(this);
482 0 : }
483 :
484 0 : void SwUndoSetFlyFmt::GetAnchor( SwFmtAnchor& rAnchor,
485 : sal_uLong nNode, xub_StrLen nCntnt )
486 : {
487 0 : RndStdIds nAnchorTyp = rAnchor.GetAnchorId();
488 0 : if (FLY_AT_PAGE != nAnchorTyp)
489 : {
490 0 : SwNode* pNd = pFrmFmt->GetDoc()->GetNodes()[ nNode ];
491 :
492 0 : if( FLY_AT_FLY == nAnchorTyp
493 0 : ? ( !pNd->IsStartNode() || SwFlyStartNode !=
494 0 : ((SwStartNode*)pNd)->GetStartNodeType() )
495 0 : : !pNd->IsTxtNode() )
496 : {
497 0 : pNd = 0; // invalid position
498 : }
499 : else
500 : {
501 0 : SwPosition aPos( *pNd );
502 0 : if ((FLY_AS_CHAR == nAnchorTyp) ||
503 : (FLY_AT_CHAR == nAnchorTyp))
504 : {
505 0 : if ( nCntnt > static_cast<SwTxtNode*>(pNd)->GetTxt().Len() )
506 : {
507 0 : pNd = 0; // invalid position
508 : }
509 : else
510 : {
511 0 : aPos.nContent.Assign(static_cast<SwTxtNode*>(pNd), nCntnt);
512 : }
513 : }
514 0 : if ( pNd )
515 : {
516 0 : rAnchor.SetAnchor( &aPos );
517 0 : }
518 : }
519 :
520 0 : if( !pNd )
521 : {
522 : // invalid position - assign first page
523 0 : rAnchor.SetType( FLY_AT_PAGE );
524 0 : rAnchor.SetPageNum( 1 );
525 : }
526 : }
527 : else
528 0 : rAnchor.SetPageNum( nCntnt );
529 0 : }
530 :
531 0 : void SwUndoSetFlyFmt::UndoImpl(::sw::UndoRedoContext & rContext)
532 : {
533 0 : SwDoc & rDoc = rContext.GetDoc();
534 :
535 : // Is the new Format still existent?
536 0 : if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmt*)pOldFmt ) )
537 : {
538 0 : if( bAnchorChgd )
539 0 : pFrmFmt->DelFrms();
540 :
541 0 : if( pFrmFmt->DerivedFrom() != pOldFmt )
542 0 : pFrmFmt->SetDerivedFrom( pOldFmt );
543 :
544 0 : SfxItemIter aIter( *pItemSet );
545 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
546 0 : while( pItem )
547 : {
548 0 : if( IsInvalidItem( pItem ))
549 : pFrmFmt->ResetFmtAttr( pItemSet->GetWhichByPos(
550 0 : aIter.GetCurPos() ));
551 : else
552 0 : pFrmFmt->SetFmtAttr( *pItem );
553 :
554 0 : if( aIter.IsAtEnd() )
555 0 : break;
556 0 : pItem = aIter.NextItem();
557 : }
558 :
559 0 : if( bAnchorChgd )
560 : {
561 0 : const SwFmtAnchor& rOldAnch = pFrmFmt->GetAnchor();
562 0 : if (FLY_AS_CHAR == rOldAnch.GetAnchorId())
563 : {
564 : // With InCntnts it's tricky: the text attribute needs to be
565 : // deleted. Unfortunately, this not only destroys the Frms but
566 : // also the format. To prevent that, first detach the
567 : // connection between attribute and format.
568 0 : const SwPosition *pPos = rOldAnch.GetCntntAnchor();
569 0 : SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
570 : OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
571 0 : const xub_StrLen nIdx = pPos->nContent.GetIndex();
572 : SwTxtAttr * pHnt = pTxtNode->GetTxtAttrForCharAt(
573 0 : nIdx, RES_TXTATR_FLYCNT );
574 : OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
575 : "Missing FlyInCnt-Hint." );
576 : OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt,
577 : "Wrong TxtFlyCnt-Hint." );
578 0 : const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
579 :
580 : // Connection is now detached, therefore the attribute can be
581 : // deleted
582 0 : pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
583 : }
584 :
585 : // reposition anchor
586 0 : SwFmtAnchor aNewAnchor( (RndStdIds) nOldAnchorTyp );
587 0 : GetAnchor( aNewAnchor, nOldNode, nOldCntnt );
588 0 : pFrmFmt->SetFmtAttr( aNewAnchor );
589 :
590 0 : if (FLY_AS_CHAR == aNewAnchor.GetAnchorId())
591 : {
592 0 : SwPosition* pPos = (SwPosition*)aNewAnchor.GetCntntAnchor();
593 0 : SwFmtFlyCnt aFmt( pFrmFmt );
594 0 : pPos->nNode.GetNode().GetTxtNode()->InsertItem( aFmt,
595 0 : nOldCntnt, 0 );
596 : }
597 :
598 0 : pFrmFmt->MakeFrms();
599 : }
600 0 : rContext.SetSelections(pFrmFmt, 0);
601 : }
602 0 : }
603 :
604 0 : void SwUndoSetFlyFmt::RedoImpl(::sw::UndoRedoContext & rContext)
605 : {
606 0 : SwDoc & rDoc = rContext.GetDoc();
607 :
608 : // Is the new Format still existent?
609 0 : if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmt*)pNewFmt ) )
610 : {
611 :
612 0 : if( bAnchorChgd )
613 : {
614 0 : SwFmtAnchor aNewAnchor( (RndStdIds) nNewAnchorTyp );
615 0 : GetAnchor( aNewAnchor, nNewNode, nNewCntnt );
616 0 : SfxItemSet aSet( rDoc.GetAttrPool(), aFrmFmtSetRange );
617 0 : aSet.Put( aNewAnchor );
618 0 : rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, &aSet );
619 : }
620 : else
621 0 : rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, 0 );
622 :
623 0 : rContext.SetSelections(pFrmFmt, 0);
624 : }
625 0 : }
626 :
627 0 : void SwUndoSetFlyFmt::PutAttr( sal_uInt16 nWhich, const SfxPoolItem* pItem )
628 : {
629 0 : if( pItem && pItem != GetDfltAttr( nWhich ) )
630 : {
631 : // Special treatment for this anchor
632 0 : if( RES_ANCHOR == nWhich )
633 : {
634 : // only keep the first change
635 : OSL_ENSURE( !bAnchorChgd, "multiple changes of an anchor are not allowed!" );
636 :
637 0 : bAnchorChgd = sal_True;
638 :
639 0 : const SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem;
640 0 : switch( nOldAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
641 : {
642 : case FLY_AS_CHAR:
643 : case FLY_AT_CHAR:
644 0 : nOldCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
645 : case FLY_AT_PARA:
646 : case FLY_AT_FLY:
647 0 : nOldNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
648 0 : break;
649 :
650 : default:
651 0 : nOldCntnt = pAnchor->GetPageNum();
652 : }
653 :
654 0 : pAnchor = (SwFmtAnchor*)&pFrmFmt->GetAnchor();
655 0 : switch( nNewAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
656 : {
657 : case FLY_AS_CHAR:
658 : case FLY_AT_CHAR:
659 0 : nNewCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex();
660 : case FLY_AT_PARA:
661 : case FLY_AT_FLY:
662 0 : nNewNode = pAnchor->GetCntntAnchor()->nNode.GetIndex();
663 0 : break;
664 :
665 : default:
666 0 : nNewCntnt = pAnchor->GetPageNum();
667 : }
668 : }
669 : else
670 0 : pItemSet->Put( *pItem );
671 : }
672 : else
673 0 : pItemSet->InvalidateItem( nWhich );
674 0 : }
675 :
676 0 : void SwUndoSetFlyFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* )
677 : {
678 0 : if( pOld )
679 : {
680 0 : sal_uInt16 nWhich = pOld->Which();
681 :
682 0 : if( nWhich < POOLATTR_END )
683 0 : PutAttr( nWhich, pOld );
684 0 : else if( RES_ATTRSET_CHG == nWhich )
685 : {
686 0 : SfxItemIter aIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
687 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
688 0 : while( pItem )
689 : {
690 0 : PutAttr( pItem->Which(), pItem );
691 0 : if( aIter.IsAtEnd() )
692 0 : break;
693 0 : pItem = aIter.NextItem();
694 0 : }
695 : }
696 : }
697 0 : }
698 :
699 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|