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