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 438 : SwUndoFlyBase::SwUndoFlyBase( SwFrameFormat* pFormat, SwUndoId nUndoId )
43 : : SwUndo(nUndoId)
44 : , pFrameFormat(pFormat)
45 : , nNdPgPos(0)
46 : , nCntPos(0)
47 : , nRndId(0)
48 438 : , bDelFormat(false)
49 : {
50 438 : }
51 :
52 876 : SwUndoFlyBase::~SwUndoFlyBase()
53 : {
54 438 : if( bDelFormat ) // delete during an Undo?
55 3 : delete pFrameFormat;
56 438 : }
57 :
58 1 : void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrm)
59 : {
60 1 : SwDoc *const pDoc = & rContext.GetDoc();
61 :
62 : // add again into array
63 1 : SwFrameFormats& rFlyFormats = *pDoc->GetSpzFrameFormats();
64 1 : rFlyFormats.push_back( pFrameFormat );
65 :
66 : // OD 26.06.2003 #108784# - insert 'master' drawing object into drawing page
67 1 : if ( RES_DRAWFRMFMT == pFrameFormat->Which() )
68 : {
69 : SwDrawContact* pDrawContact =
70 0 : static_cast<SwDrawContact*>(pFrameFormat->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 1 : SwFormatAnchor aAnchor( (RndStdIds)nRndId );
81 :
82 1 : if (FLY_AT_PAGE == nRndId)
83 : {
84 0 : aAnchor.SetPageNum( (sal_uInt16)nNdPgPos );
85 : }
86 : else
87 : {
88 1 : SwPosition aNewPos(pDoc->GetNodes().GetEndOfContent());
89 1 : aNewPos.nNode = nNdPgPos;
90 1 : if ((FLY_AS_CHAR == nRndId) || (FLY_AT_CHAR == nRndId))
91 : {
92 1 : aNewPos.nContent.Assign( aNewPos.nNode.GetNode().GetContentNode(),
93 2 : nCntPos );
94 : }
95 1 : aAnchor.SetAnchor( &aNewPos );
96 : }
97 :
98 1 : pFrameFormat->SetFormatAttr( aAnchor ); // reset anchor
99 :
100 1 : if( RES_DRAWFRMFMT != pFrameFormat->Which() )
101 : {
102 : // get Content and reset ContentAttribute
103 1 : SwNodeIndex aIdx( pDoc->GetNodes() );
104 1 : RestoreSection( pDoc, &aIdx, SwFlyStartNode );
105 1 : pFrameFormat->SetFormatAttr( SwFormatContent( aIdx.GetNode().GetStartNode() ));
106 : }
107 :
108 : // Set InContentAttribute 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 1 : if (FLY_AS_CHAR == nRndId)
112 : {
113 : // there must be at least the attribute in a TextNode
114 1 : SwContentNode* pCNd = aAnchor.GetContentAnchor()->nNode.GetNode().GetContentNode();
115 : OSL_ENSURE( pCNd->IsTextNode(), "no Text Node at position." );
116 1 : SwFormatFlyCnt aFormat( pFrameFormat );
117 1 : pCNd->GetTextNode()->InsertItem( aFormat, nCntPos, nCntPos );
118 : }
119 :
120 1 : pFrameFormat->MakeFrms();
121 :
122 1 : if( bShowSelFrm )
123 : {
124 0 : rContext.SetSelections(pFrameFormat, 0);
125 : }
126 :
127 1 : if( GetHistory() )
128 0 : GetHistory()->Rollback( pDoc );
129 :
130 1 : switch( nRndId )
131 : {
132 : case FLY_AS_CHAR:
133 : case FLY_AT_CHAR:
134 : {
135 1 : const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
136 1 : nNdPgPos = rAnchor.GetContentAnchor()->nNode.GetIndex();
137 1 : nCntPos = rAnchor.GetContentAnchor()->nContent.GetIndex();
138 : }
139 1 : break;
140 : case FLY_AT_PARA:
141 : case FLY_AT_FLY:
142 : {
143 0 : const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
144 0 : nNdPgPos = rAnchor.GetContentAnchor()->nNode.GetIndex();
145 : }
146 0 : break;
147 : case FLY_AT_PAGE:
148 0 : break;
149 : }
150 1 : bDelFormat = false;
151 1 : }
152 :
153 4 : void SwUndoFlyBase::DelFly( SwDoc* pDoc )
154 : {
155 4 : bDelFormat = true; // delete Format in DTOR
156 4 : pFrameFormat->DelFrms(); // destroy Frms
157 :
158 : // all Uno objects should now log themselves off
159 : {
160 4 : SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFrameFormat );
161 4 : pFrameFormat->ModifyNotification( &aMsgHint, &aMsgHint );
162 : }
163 :
164 4 : if ( RES_DRAWFRMFMT != pFrameFormat->Which() )
165 : {
166 : // if there is content than save it
167 3 : const SwFormatContent& rContent = pFrameFormat->GetContent();
168 : OSL_ENSURE( rContent.GetContentIdx(), "Fly ohne Inhalt" );
169 :
170 3 : SaveSection( *rContent.GetContentIdx() );
171 3 : const_cast<SwFormatContent&>(rContent).SetNewContentIdx( nullptr );
172 : }
173 : // OD 02.07.2003 #108784# - remove 'master' drawing object from drawing page
174 1 : else if ( RES_DRAWFRMFMT == pFrameFormat->Which() )
175 : {
176 : SwDrawContact* pDrawContact =
177 1 : static_cast<SwDrawContact*>(pFrameFormat->FindContactObj());
178 1 : if ( pDrawContact )
179 : {
180 1 : pDrawContact->RemoveMasterFromDrawPage();
181 : }
182 : }
183 :
184 4 : const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
185 4 : const SwPosition* pPos = rAnchor.GetContentAnchor();
186 : // The positions in Nodes array got shifted.
187 4 : nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
188 4 : if (FLY_AS_CHAR == nRndId)
189 : {
190 2 : nNdPgPos = pPos->nNode.GetIndex();
191 2 : nCntPos = pPos->nContent.GetIndex();
192 2 : SwTextNode *const pTextNd = pPos->nNode.GetNode().GetTextNode();
193 : OSL_ENSURE( pTextNd, "Kein Textnode gefunden" );
194 : SwTextFlyCnt* const pAttr = static_cast<SwTextFlyCnt*>(
195 2 : pTextNd->GetTextAttrForCharAt( nCntPos, RES_TXTATR_FLYCNT ) );
196 : // attribute is still in TextNode, delete
197 2 : if( pAttr && pAttr->GetFlyCnt().GetFrameFormat() == pFrameFormat )
198 : {
199 : // Pointer to 0, do not delete
200 1 : const_cast<SwFormatFlyCnt&>(pAttr->GetFlyCnt()).SetFlyFormat();
201 1 : SwIndex aIdx( pPos->nContent );
202 1 : pTextNd->EraseText( aIdx, 1 );
203 : }
204 : }
205 2 : else if (FLY_AT_CHAR == nRndId)
206 : {
207 0 : nNdPgPos = pPos->nNode.GetIndex();
208 0 : nCntPos = pPos->nContent.GetIndex();
209 : }
210 2 : else if ((FLY_AT_PARA == nRndId) || (FLY_AT_FLY == nRndId))
211 : {
212 1 : nNdPgPos = pPos->nNode.GetIndex();
213 : }
214 : else
215 : {
216 1 : nNdPgPos = rAnchor.GetPageNum();
217 : }
218 :
219 4 : pFrameFormat->ResetFormatAttr( RES_ANCHOR ); // delete anchor
220 :
221 : // delete from array
222 4 : SwFrameFormats& rFlyFormats = *pDoc->GetSpzFrameFormats();
223 4 : rFlyFormats.erase( std::find( rFlyFormats.begin(), rFlyFormats.end(), pFrameFormat ));
224 4 : }
225 :
226 434 : SwUndoInsLayFormat::SwUndoInsLayFormat( SwFrameFormat* pFormat, sal_uLong nNodeIdx, sal_Int32 nCntIdx )
227 434 : : SwUndoFlyBase( pFormat, RES_DRAWFRMFMT == pFormat->Which() ?
228 : UNDO_INSDRAWFMT : UNDO_INSLAYFMT ),
229 434 : mnCrsrSaveIndexPara( nNodeIdx ), mnCrsrSaveIndexPos( nCntIdx )
230 : {
231 434 : const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
232 434 : nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId());
233 434 : bDelFormat = false;
234 434 : switch( nRndId )
235 : {
236 : case FLY_AT_PAGE:
237 105 : nNdPgPos = rAnchor.GetPageNum();
238 105 : break;
239 : case FLY_AT_PARA:
240 : case FLY_AT_FLY:
241 16 : nNdPgPos = rAnchor.GetContentAnchor()->nNode.GetIndex();
242 16 : break;
243 : case FLY_AS_CHAR:
244 : case FLY_AT_CHAR:
245 : {
246 313 : const SwPosition* pPos = rAnchor.GetContentAnchor();
247 313 : nCntPos = pPos->nContent.GetIndex();
248 313 : nNdPgPos = pPos->nNode.GetIndex();
249 : }
250 313 : break;
251 : default:
252 : OSL_FAIL( "Which FlyFrame?" );
253 : }
254 434 : }
255 :
256 868 : SwUndoInsLayFormat::~SwUndoInsLayFormat()
257 : {
258 868 : }
259 :
260 0 : void SwUndoInsLayFormat::UndoImpl(::sw::UndoRedoContext & rContext)
261 : {
262 0 : SwDoc & rDoc(rContext.GetDoc());
263 0 : const SwFormatContent& rContent = pFrameFormat->GetContent();
264 0 : if( rContent.GetContentIdx() ) // no content
265 : {
266 0 : bool bRemoveIdx = true;
267 0 : if( mnCrsrSaveIndexPara > 0 )
268 : {
269 : SwTextNode *const pNode =
270 0 : rDoc.GetNodes()[mnCrsrSaveIndexPara]->GetTextNode();
271 0 : if( pNode )
272 : {
273 0 : SwNodeIndex aIdx( rDoc.GetNodes(),
274 0 : rContent.GetContentIdx()->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 : SwDoc::CorrAbs( aIdx, aEndIdx, aPos, true );
280 0 : bRemoveIdx = false;
281 : }
282 : }
283 0 : if( bRemoveIdx )
284 : {
285 0 : RemoveIdxFromSection( rDoc, rContent.GetContentIdx()->GetIndex() );
286 : }
287 : }
288 0 : DelFly(& rDoc);
289 0 : }
290 :
291 0 : void SwUndoInsLayFormat::RedoImpl(::sw::UndoRedoContext & rContext)
292 : {
293 0 : InsFly(rContext);
294 0 : }
295 :
296 0 : void SwUndoInsLayFormat::RepeatImpl(::sw::RepeatContext & rContext)
297 : {
298 0 : SwDoc *const pDoc = & rContext.GetDoc();
299 : // get anchor and reset it
300 0 : SwFormatAnchor aAnchor( pFrameFormat->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 : SwFrameFormat* pFlyFormat = pDoc->getIDocumentLayoutAccess().CopyLayoutFormat( *pFrameFormat, aAnchor, true, true );
335 0 : (void) pFlyFormat;
336 : }
337 :
338 : // #111827#
339 499 : OUString SwUndoInsLayFormat::GetComment() const
340 : {
341 499 : OUString aResult;
342 :
343 : // HACK: disable caching:
344 : // the SfxUndoManager calls GetComment() too early: the pFrameFormat 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 499 : bool bDone = false;
355 499 : if (pFrameFormat)
356 : {
357 499 : const SdrObject * pSdrObj = pFrameFormat->FindSdrObject();
358 499 : if ( pSdrObj )
359 : {
360 430 : aResult = SdrUndoNewObj::GetComment( *pSdrObj );
361 430 : bDone = true;
362 : }
363 : }
364 :
365 499 : if (! bDone)
366 69 : aResult = SwUndo::GetComment();
367 : }
368 : else
369 : aResult = *pComment;
370 :
371 499 : return aResult;
372 : }
373 :
374 : static SwUndoId
375 4 : lcl_GetSwUndoId(SwFrameFormat *const pFrameFormat)
376 : {
377 4 : if (RES_DRAWFRMFMT != pFrameFormat->Which())
378 : {
379 3 : const SwFormatContent& rContent = pFrameFormat->GetContent();
380 : OSL_ENSURE( rContent.GetContentIdx(), "Fly without content" );
381 :
382 3 : SwNodeIndex firstNode(*rContent.GetContentIdx(), 1);
383 3 : SwNoTextNode *const pNoTextNode(firstNode.GetNode().GetNoTextNode());
384 3 : if (pNoTextNode && pNoTextNode->IsGrfNode())
385 : {
386 1 : return UNDO_DELGRF;
387 : }
388 2 : else if (pNoTextNode && pNoTextNode->IsOLENode())
389 : {
390 : // surprisingly not UNDO_DELOLE, which does not seem to work
391 0 : return UNDO_DELETE;
392 2 : }
393 : }
394 3 : return UNDO_DELLAYFMT;
395 : }
396 :
397 4 : SwUndoDelLayFormat::SwUndoDelLayFormat( SwFrameFormat* pFormat )
398 : : SwUndoFlyBase( pFormat, lcl_GetSwUndoId(pFormat) )
399 4 : , bShowSelFrm( true )
400 : {
401 4 : SwDoc* pDoc = pFormat->GetDoc();
402 4 : DelFly( pDoc );
403 4 : }
404 :
405 3 : SwRewriter SwUndoDelLayFormat::GetRewriter() const
406 : {
407 3 : SwRewriter aRewriter;
408 :
409 3 : SwDoc * pDoc = pFrameFormat->GetDoc();
410 :
411 3 : if (pDoc)
412 : {
413 3 : SwNodeIndex* pIdx = GetMvSttIdx();
414 3 : if( 1 == GetMvNodeCnt() && pIdx)
415 : {
416 2 : SwNode *const pNd = & pIdx->GetNode();
417 :
418 2 : if ( pNd->IsNoTextNode() && pNd->IsOLENode())
419 : {
420 0 : SwOLENode * pOLENd = pNd->GetOLENode();
421 :
422 0 : aRewriter.AddRule(UndoArg1, pOLENd->GetDescription());
423 : }
424 : }
425 : }
426 :
427 3 : return aRewriter;
428 : }
429 :
430 1 : void SwUndoDelLayFormat::UndoImpl(::sw::UndoRedoContext & rContext)
431 : {
432 1 : InsFly( rContext, bShowSelFrm );
433 1 : }
434 :
435 0 : void SwUndoDelLayFormat::RedoImpl(::sw::UndoRedoContext & rContext)
436 : {
437 0 : SwDoc & rDoc(rContext.GetDoc());
438 0 : const SwFormatContent& rContent = pFrameFormat->GetContent();
439 0 : if( rContent.GetContentIdx() ) // no content
440 : {
441 0 : RemoveIdxFromSection(rDoc, rContent.GetContentIdx()->GetIndex());
442 : }
443 :
444 0 : DelFly(& rDoc);
445 0 : }
446 :
447 0 : void SwUndoDelLayFormat::RedoForRollback()
448 : {
449 0 : const SwFormatContent& rContent = pFrameFormat->GetContent();
450 0 : if( rContent.GetContentIdx() ) // no content
451 0 : RemoveIdxFromSection( *pFrameFormat->GetDoc(),
452 0 : rContent.GetContentIdx()->GetIndex() );
453 :
454 0 : DelFly( pFrameFormat->GetDoc() );
455 0 : }
456 :
457 5 : SwUndoSetFlyFormat::SwUndoSetFlyFormat( SwFrameFormat& rFlyFormat, SwFrameFormat& rNewFrameFormat )
458 : : SwUndo( UNDO_SETFLYFRMFMT ), SwClient( &rFlyFormat ), pFrameFormat( &rFlyFormat ),
459 5 : pOldFormat( static_cast<SwFrameFormat*>(rFlyFormat.DerivedFrom()) ), pNewFormat( &rNewFrameFormat ),
460 5 : pItemSet( new SfxItemSet( *rFlyFormat.GetAttrSet().GetPool(),
461 10 : rFlyFormat.GetAttrSet().GetRanges() )),
462 : nOldNode( 0 ), nNewNode( 0 ),
463 : nOldContent( 0 ), nNewContent( 0 ),
464 25 : nOldAnchorTyp( 0 ), nNewAnchorTyp( 0 ), bAnchorChgd( false )
465 : {
466 5 : }
467 :
468 5 : SwRewriter SwUndoSetFlyFormat::GetRewriter() const
469 : {
470 5 : SwRewriter aRewriter;
471 :
472 5 : if (pNewFormat)
473 5 : aRewriter.AddRule(UndoArg1, pNewFormat->GetName());
474 :
475 5 : return aRewriter;
476 : }
477 :
478 15 : SwUndoSetFlyFormat::~SwUndoSetFlyFormat()
479 : {
480 5 : delete pItemSet;
481 10 : }
482 :
483 5 : void SwUndoSetFlyFormat::DeRegisterFromFormat( SwFormat& rFormat )
484 : {
485 5 : rFormat.Remove(this);
486 5 : }
487 :
488 0 : void SwUndoSetFlyFormat::GetAnchor( SwFormatAnchor& rAnchor,
489 : sal_uLong nNode, sal_Int32 nContent )
490 : {
491 0 : RndStdIds nAnchorTyp = rAnchor.GetAnchorId();
492 0 : if (FLY_AT_PAGE != nAnchorTyp)
493 : {
494 0 : SwNode* pNd = pFrameFormat->GetDoc()->GetNodes()[ nNode ];
495 :
496 0 : if( FLY_AT_FLY == nAnchorTyp
497 0 : ? ( !pNd->IsStartNode() || SwFlyStartNode !=
498 0 : static_cast<SwStartNode*>(pNd)->GetStartNodeType() )
499 0 : : !pNd->IsTextNode() )
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 (nContent > pNd->GetTextNode()->GetText().getLength())
510 : {
511 0 : pNd = 0; // invalid position
512 : }
513 : else
514 : {
515 0 : aPos.nContent.Assign(pNd->GetTextNode(), nContent);
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( nContent );
533 0 : }
534 :
535 0 : void SwUndoSetFlyFormat::UndoImpl(::sw::UndoRedoContext & rContext)
536 : {
537 0 : SwDoc & rDoc = rContext.GetDoc();
538 :
539 : // Is the new Format still existent?
540 0 : if( rDoc.GetFrameFormats()->Contains( pOldFormat ) )
541 : {
542 0 : if( bAnchorChgd )
543 0 : pFrameFormat->DelFrms();
544 :
545 0 : if( pFrameFormat->DerivedFrom() != pOldFormat )
546 0 : pFrameFormat->SetDerivedFrom( pOldFormat );
547 :
548 0 : SfxItemIter aIter( *pItemSet );
549 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
550 0 : while( pItem )
551 : {
552 0 : if( IsInvalidItem( pItem ))
553 : pFrameFormat->ResetFormatAttr( pItemSet->GetWhichByPos(
554 0 : aIter.GetCurPos() ));
555 : else
556 0 : pFrameFormat->SetFormatAttr( *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 SwFormatAnchor& rOldAnch = pFrameFormat->GetAnchor();
566 0 : if (FLY_AS_CHAR == rOldAnch.GetAnchorId())
567 : {
568 : // With InContents 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.GetContentAnchor();
573 0 : SwTextNode *pTextNode = pPos->nNode.GetNode().GetTextNode();
574 : OSL_ENSURE( pTextNode->HasHints(), "Missing FlyInCnt-Hint." );
575 0 : const sal_Int32 nIdx = pPos->nContent.GetIndex();
576 : SwTextAttr * pHint = pTextNode->GetTextAttrForCharAt(
577 0 : nIdx, RES_TXTATR_FLYCNT );
578 : OSL_ENSURE( pHint && pHint->Which() == RES_TXTATR_FLYCNT,
579 : "Missing FlyInCnt-Hint." );
580 : OSL_ENSURE( pHint && pHint->GetFlyCnt().GetFrameFormat() == pFrameFormat,
581 : "Wrong TextFlyCnt-Hint." );
582 0 : const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt()).SetFlyFormat();
583 :
584 : // Connection is now detached, therefore the attribute can be
585 : // deleted
586 0 : pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
587 : }
588 :
589 : // reposition anchor
590 0 : SwFormatAnchor aNewAnchor( (RndStdIds) nOldAnchorTyp );
591 0 : GetAnchor( aNewAnchor, nOldNode, nOldContent );
592 0 : pFrameFormat->SetFormatAttr( aNewAnchor );
593 :
594 0 : if (FLY_AS_CHAR == aNewAnchor.GetAnchorId())
595 : {
596 0 : const SwPosition* pPos = aNewAnchor.GetContentAnchor();
597 0 : SwFormatFlyCnt aFormat( pFrameFormat );
598 0 : pPos->nNode.GetNode().GetTextNode()->InsertItem( aFormat,
599 0 : nOldContent, 0 );
600 : }
601 :
602 0 : pFrameFormat->MakeFrms();
603 : }
604 0 : rContext.SetSelections(pFrameFormat, 0);
605 : }
606 0 : }
607 :
608 0 : void SwUndoSetFlyFormat::RedoImpl(::sw::UndoRedoContext & rContext)
609 : {
610 0 : SwDoc & rDoc = rContext.GetDoc();
611 :
612 : // Is the new Format still existent?
613 0 : if( rDoc.GetFrameFormats()->Contains( pNewFormat ) )
614 : {
615 :
616 0 : if( bAnchorChgd )
617 : {
618 0 : SwFormatAnchor aNewAnchor( (RndStdIds) nNewAnchorTyp );
619 0 : GetAnchor( aNewAnchor, nNewNode, nNewContent );
620 0 : SfxItemSet aSet( rDoc.GetAttrPool(), aFrameFormatSetRange );
621 0 : aSet.Put( aNewAnchor );
622 0 : rDoc.SetFrameFormatToFly( *pFrameFormat, *pNewFormat, &aSet );
623 : }
624 : else
625 0 : rDoc.SetFrameFormatToFly( *pFrameFormat, *pNewFormat, 0 );
626 :
627 0 : rContext.SetSelections(pFrameFormat, 0);
628 : }
629 0 : }
630 :
631 0 : void SwUndoSetFlyFormat::PutAttr( sal_uInt16 nWhich, const SfxPoolItem* pItem )
632 : {
633 0 : if( pItem && pItem != GetDfltAttr( nWhich ) )
634 : {
635 : // Special treatment for this anchor
636 0 : 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 0 : bAnchorChgd = true;
642 :
643 0 : const SwFormatAnchor* pAnchor = static_cast<const SwFormatAnchor*>(pItem);
644 0 : switch( nOldAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
645 : {
646 : case FLY_AS_CHAR:
647 : case FLY_AT_CHAR:
648 0 : nOldContent = pAnchor->GetContentAnchor()->nContent.GetIndex();
649 : //fall-through
650 : case FLY_AT_PARA:
651 : case FLY_AT_FLY:
652 0 : nOldNode = pAnchor->GetContentAnchor()->nNode.GetIndex();
653 0 : break;
654 :
655 : default:
656 0 : nOldContent = pAnchor->GetPageNum();
657 : }
658 :
659 0 : pAnchor = &pFrameFormat->GetAnchor();
660 0 : switch( nNewAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) )
661 : {
662 : case FLY_AS_CHAR:
663 : case FLY_AT_CHAR:
664 0 : nNewContent = pAnchor->GetContentAnchor()->nContent.GetIndex();
665 : //fall-through
666 : case FLY_AT_PARA:
667 : case FLY_AT_FLY:
668 0 : nNewNode = pAnchor->GetContentAnchor()->nNode.GetIndex();
669 0 : break;
670 :
671 : default:
672 0 : nNewContent = pAnchor->GetPageNum();
673 : }
674 : }
675 : else
676 0 : pItemSet->Put( *pItem );
677 : }
678 : else
679 0 : pItemSet->InvalidateItem( nWhich );
680 0 : }
681 :
682 5 : void SwUndoSetFlyFormat::Modify( const SfxPoolItem* pOld, const SfxPoolItem* )
683 : {
684 5 : if( pOld )
685 : {
686 5 : sal_uInt16 nWhich = pOld->Which();
687 :
688 5 : if( nWhich < POOLATTR_END )
689 0 : PutAttr( nWhich, pOld );
690 5 : else if( RES_ATTRSET_CHG == nWhich )
691 : {
692 0 : SfxItemIter aIter( *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet() );
693 0 : const SfxPoolItem* pItem = aIter.GetCurItem();
694 0 : while( pItem )
695 : {
696 0 : PutAttr( pItem->Which(), pItem );
697 0 : if( aIter.IsAtEnd() )
698 0 : break;
699 0 : pItem = aIter.NextItem();
700 0 : }
701 : }
702 : }
703 182 : }
704 :
705 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|