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 <hintids.hxx>
21 : #include <svl/itemiter.hxx>
22 : #include <svx/svdobj.hxx>
23 : #include <svx/svdpage.hxx>
24 : #include <svx/svdmodel.hxx>
25 : #include <svx/svdocapt.hxx>
26 : #include <svx/svdmark.hxx>
27 : #include <fmtfsize.hxx>
28 : #include <fmtornt.hxx>
29 : #include <fmtsrnd.hxx>
30 : #include <dcontact.hxx>
31 :
32 : #include <ndgrf.hxx>
33 : #include <doc.hxx>
34 : #include <IDocumentUndoRedo.hxx>
35 : #include <ndindex.hxx>
36 : #include <docary.hxx>
37 : #include <fmtcntnt.hxx>
38 : #include <fmtanchr.hxx>
39 : #include <txtflcnt.hxx>
40 : #include <fmtflcnt.hxx>
41 : #include <txtfrm.hxx>
42 : #include <pagefrm.hxx>
43 : #include <rootfrm.hxx>
44 : #include <flyfrms.hxx>
45 : #include <frmtool.hxx>
46 : #include <frmfmt.hxx>
47 : #include <ndtxt.hxx>
48 : #include <pam.hxx>
49 : #include <tblsel.hxx>
50 : #include <swundo.hxx>
51 : #include <swtable.hxx>
52 : #include <crstate.hxx>
53 : #include <UndoCore.hxx>
54 : #include <UndoAttribute.hxx>
55 : #include <fmtcnct.hxx>
56 : #include <dflyobj.hxx>
57 : #include <undoflystrattr.hxx>
58 : #include <switerator.hxx>
59 : #include <boost/scoped_ptr.hpp>
60 :
61 : //UUUU
62 : #include <svx/xbtmpit.hxx>
63 : #include <svx/xflftrit.hxx>
64 : #include <svx/xlndsit.hxx>
65 : #include <svx/xlnstit.hxx>
66 : #include <svx/xlnedit.hxx>
67 : #include <svx/xflhtit.hxx>
68 :
69 : extern sal_uInt16 GetHtmlMode( const SwDocShell* );
70 :
71 : using namespace ::com::sun::star;
72 :
73 0 : sal_uInt16 SwDoc::GetFlyCount( FlyCntType eType ) const
74 : {
75 0 : const SwFrmFmts& rFmts = *GetSpzFrmFmts();
76 0 : sal_uInt16 nSize = rFmts.size();
77 0 : sal_uInt16 nCount = 0;
78 : const SwNodeIndex* pIdx;
79 0 : for ( sal_uInt16 i = 0; i < nSize; i++)
80 : {
81 0 : const SwFrmFmt* pFlyFmt = rFmts[ i ];
82 0 : if( RES_FLYFRMFMT == pFlyFmt->Which()
83 0 : && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
84 0 : && pIdx->GetNodes().IsDocNodes()
85 : )
86 : {
87 0 : const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
88 :
89 0 : switch( eType )
90 : {
91 : case FLYCNTTYPE_FRM:
92 0 : if(!pNd->IsNoTxtNode())
93 0 : nCount++;
94 0 : break;
95 :
96 : case FLYCNTTYPE_GRF:
97 0 : if( pNd->IsGrfNode() )
98 0 : nCount++;
99 0 : break;
100 :
101 : case FLYCNTTYPE_OLE:
102 0 : if(pNd->IsOLENode())
103 0 : nCount++;
104 0 : break;
105 :
106 : default:
107 0 : nCount++;
108 : }
109 : }
110 : }
111 0 : return nCount;
112 : }
113 :
114 : /// @attention If you change this, also update SwXFrameEnumeration in unocoll.
115 0 : SwFrmFmt* SwDoc::GetFlyNum( sal_uInt16 nIdx, FlyCntType eType )
116 : {
117 0 : SwFrmFmts& rFmts = *GetSpzFrmFmts();
118 0 : SwFrmFmt* pRetFmt = 0;
119 0 : sal_uInt16 nSize = rFmts.size();
120 : const SwNodeIndex* pIdx;
121 0 : sal_uInt16 nCount = 0;
122 0 : for( sal_uInt16 i = 0; !pRetFmt && i < nSize; ++i )
123 : {
124 0 : SwFrmFmt* pFlyFmt = rFmts[ i ];
125 0 : if( RES_FLYFRMFMT == pFlyFmt->Which()
126 0 : && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
127 0 : && pIdx->GetNodes().IsDocNodes()
128 : )
129 : {
130 0 : const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
131 0 : switch( eType )
132 : {
133 : case FLYCNTTYPE_FRM:
134 0 : if( !pNd->IsNoTxtNode() && nIdx == nCount++)
135 0 : pRetFmt = pFlyFmt;
136 0 : break;
137 : case FLYCNTTYPE_GRF:
138 0 : if(pNd->IsGrfNode() && nIdx == nCount++ )
139 0 : pRetFmt = pFlyFmt;
140 0 : break;
141 : case FLYCNTTYPE_OLE:
142 0 : if(pNd->IsOLENode() && nIdx == nCount++)
143 0 : pRetFmt = pFlyFmt;
144 0 : break;
145 : default:
146 0 : if(nIdx == nCount++)
147 0 : pRetFmt = pFlyFmt;
148 : }
149 : }
150 : }
151 0 : return pRetFmt;
152 : }
153 :
154 0 : static Point lcl_FindAnchorLayPos( SwDoc& rDoc, const SwFmtAnchor& rAnch,
155 : const SwFrmFmt* pFlyFmt )
156 : {
157 0 : Point aRet;
158 0 : if( rDoc.GetCurrentViewShell() )
159 0 : switch( rAnch.GetAnchorId() )
160 : {
161 : case FLY_AS_CHAR:
162 0 : if( pFlyFmt && rAnch.GetCntntAnchor() )
163 : {
164 0 : const SwFrm* pOld = ((SwFlyFrmFmt*)pFlyFmt)->GetFrm( &aRet, sal_False );
165 0 : if( pOld )
166 0 : aRet = pOld->Frm().Pos();
167 : }
168 0 : break;
169 :
170 : case FLY_AT_PARA:
171 : case FLY_AT_CHAR: // LAYER_IMPL
172 0 : if( rAnch.GetCntntAnchor() )
173 : {
174 0 : const SwPosition *pPos = rAnch.GetCntntAnchor();
175 0 : const SwCntntNode* pNd = pPos->nNode.GetNode().GetCntntNode();
176 0 : const SwFrm* pOld = pNd ? pNd->getLayoutFrm( rDoc.GetCurrentLayout(), &aRet, 0, false ) : 0;
177 0 : if( pOld )
178 0 : aRet = pOld->Frm().Pos();
179 : }
180 0 : break;
181 :
182 : case FLY_AT_FLY: // LAYER_IMPL
183 0 : if( rAnch.GetCntntAnchor() )
184 : {
185 0 : const SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)rAnch.GetCntntAnchor()->
186 0 : nNode.GetNode().GetFlyFmt();
187 0 : const SwFrm* pOld = pFmt ? pFmt->GetFrm( &aRet, sal_False ) : 0;
188 0 : if( pOld )
189 0 : aRet = pOld->Frm().Pos();
190 : }
191 0 : break;
192 :
193 : case FLY_AT_PAGE:
194 : {
195 0 : sal_uInt16 nPgNum = rAnch.GetPageNum();
196 0 : const SwPageFrm *pPage = (SwPageFrm*)rDoc.GetCurrentLayout()->Lower();
197 0 : for( sal_uInt16 i = 1; (i <= nPgNum) && pPage; ++i,
198 0 : pPage = (const SwPageFrm*)pPage->GetNext() )
199 0 : if( i == nPgNum )
200 : {
201 0 : aRet = pPage->Frm().Pos();
202 0 : break;
203 : }
204 : }
205 0 : break;
206 : default:
207 0 : break;
208 : }
209 0 : return aRet;
210 : }
211 :
212 : #define MAKEFRMS 0
213 : #define IGNOREANCHOR 1
214 : #define DONTMAKEFRMS 2
215 :
216 0 : sal_Int8 SwDoc::SetFlyFrmAnchor( SwFrmFmt& rFmt, SfxItemSet& rSet, bool bNewFrms )
217 : {
218 : // Changing anchors is almost always allowed.
219 : // Exception: Paragraph and character bound frames must not become
220 : // page bound, if they are located in the header or footer.
221 0 : const SwFmtAnchor &rOldAnch = rFmt.GetAnchor();
222 0 : const RndStdIds nOld = rOldAnch.GetAnchorId();
223 :
224 0 : SwFmtAnchor aNewAnch( (SwFmtAnchor&)rSet.Get( RES_ANCHOR ) );
225 0 : RndStdIds nNew = aNewAnch.GetAnchorId();
226 :
227 : // Is the new anchor valid?
228 0 : if( !aNewAnch.GetCntntAnchor() && (FLY_AT_FLY == nNew ||
229 0 : (FLY_AT_PARA == nNew) || (FLY_AS_CHAR == nNew) ||
230 : (FLY_AT_CHAR == nNew) ))
231 : {
232 0 : return IGNOREANCHOR;
233 : }
234 :
235 0 : if( nOld == nNew )
236 0 : return DONTMAKEFRMS;
237 :
238 0 : Point aOldAnchorPos( ::lcl_FindAnchorLayPos( *this, rOldAnch, &rFmt ));
239 0 : Point aNewAnchorPos( ::lcl_FindAnchorLayPos( *this, aNewAnch, 0 ));
240 :
241 : // Destroy the old Frames.
242 : // The Views are hidden implicitly, so hiding them another time would be
243 : // kind of a show!
244 0 : rFmt.DelFrms();
245 :
246 0 : if ( FLY_AS_CHAR == nOld )
247 : {
248 : // We need to handle InCntnts in a special way:
249 : // The TxtAttribut needs to be destroyed which, unfortunately, also
250 : // destroys the format. To avoid that, we disconnect the format from
251 : // the attribute.
252 0 : const SwPosition *pPos = rOldAnch.GetCntntAnchor();
253 0 : SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
254 : OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
255 0 : const sal_Int32 nIdx = pPos->nContent.GetIndex();
256 : SwTxtAttr * const pHnt =
257 0 : pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
258 : OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
259 : "Missing FlyInCnt-Hint." );
260 : OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == &rFmt,
261 : "Wrong TxtFlyCnt-Hint." );
262 0 : if (pHnt)
263 0 : const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
264 :
265 : // They are disconnected. We now have to destroy the attribute.
266 0 : pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
267 : }
268 :
269 : // We can finally set the attribute. It needs to be the first one!
270 : // Undo depends on it!
271 0 : rFmt.SetFmtAttr( aNewAnch );
272 :
273 : // Correct the position
274 : const SfxPoolItem* pItem;
275 0 : switch( nNew )
276 : {
277 : case FLY_AS_CHAR:
278 : // If no position attributes are received, we have to make sure
279 : // that no forbidden automatic alignment is left.
280 : {
281 0 : const SwPosition *pPos = aNewAnch.GetCntntAnchor();
282 0 : SwTxtNode *pNd = pPos->nNode.GetNode().GetTxtNode();
283 : OSL_ENSURE( pNd, "Crsr does not point to TxtNode." );
284 :
285 0 : SwFmtFlyCnt aFmt( static_cast<SwFlyFrmFmt*>(&rFmt) );
286 0 : pNd->InsertItem( aFmt, pPos->nContent.GetIndex(), 0 );
287 : }
288 :
289 0 : if( SFX_ITEM_SET != rSet.GetItemState( RES_VERT_ORIENT, false, &pItem ))
290 : {
291 0 : SwFmtVertOrient aOldV( rFmt.GetVertOrient() );
292 0 : bool bSet = true;
293 0 : switch( aOldV.GetVertOrient() )
294 : {
295 0 : case text::VertOrientation::LINE_TOP: aOldV.SetVertOrient( text::VertOrientation::TOP ); break;
296 0 : case text::VertOrientation::LINE_CENTER: aOldV.SetVertOrient( text::VertOrientation::CENTER); break;
297 0 : case text::VertOrientation::LINE_BOTTOM: aOldV.SetVertOrient( text::VertOrientation::BOTTOM); break;
298 0 : case text::VertOrientation::NONE: aOldV.SetVertOrient( text::VertOrientation::CENTER); break;
299 : default:
300 0 : bSet = false;
301 : }
302 0 : if( bSet )
303 0 : rSet.Put( aOldV );
304 : }
305 0 : break;
306 :
307 : case FLY_AT_PARA:
308 : case FLY_AT_CHAR: // LAYER_IMPL
309 : case FLY_AT_FLY: // LAYER_IMPL
310 : case FLY_AT_PAGE:
311 : {
312 : // If no position attributes are coming in, we correct the position in a way
313 : // such that the fly's document coordinates are preserved.
314 : // If only the alignment changes in the position attributes (text::RelOrientation::FRAME
315 : // vs. text::RelOrientation::PRTAREA), we also correct the position.
316 0 : if( SFX_ITEM_SET != rSet.GetItemState( RES_HORI_ORIENT, false, &pItem ))
317 0 : pItem = 0;
318 :
319 0 : SwFmtHoriOrient aOldH( rFmt.GetHoriOrient() );
320 :
321 0 : if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( !pItem ||
322 0 : aOldH.GetPos() == ((SwFmtHoriOrient*)pItem)->GetPos() ))
323 : {
324 0 : SwTwips nPos = (FLY_AS_CHAR == nOld) ? 0 : aOldH.GetPos();
325 0 : nPos += aOldAnchorPos.getX() - aNewAnchorPos.getX();
326 :
327 0 : if( pItem )
328 : {
329 0 : SwFmtHoriOrient* pH = (SwFmtHoriOrient*)pItem;
330 0 : aOldH.SetHoriOrient( pH->GetHoriOrient() );
331 0 : aOldH.SetRelationOrient( pH->GetRelationOrient() );
332 : }
333 0 : aOldH.SetPos( nPos );
334 0 : rSet.Put( aOldH );
335 : }
336 :
337 0 : if( SFX_ITEM_SET != rSet.GetItemState( RES_VERT_ORIENT, false, &pItem ))
338 0 : pItem = 0;
339 0 : SwFmtVertOrient aOldV( rFmt.GetVertOrient() );
340 :
341 : // #i28922# - correction: compare <aOldV.GetVertOrient() with
342 : // <text::VertOrientation::NONE>
343 0 : if( text::VertOrientation::NONE == aOldV.GetVertOrient() && (!pItem ||
344 0 : aOldV.GetPos() == ((SwFmtVertOrient*)pItem)->GetPos() ) )
345 : {
346 0 : SwTwips nPos = (FLY_AS_CHAR == nOld) ? 0 : aOldV.GetPos();
347 0 : nPos += aOldAnchorPos.getY() - aNewAnchorPos.getY();
348 0 : if( pItem )
349 : {
350 0 : SwFmtVertOrient* pV = (SwFmtVertOrient*)pItem;
351 0 : aOldV.SetVertOrient( pV->GetVertOrient() );
352 0 : aOldV.SetRelationOrient( pV->GetRelationOrient() );
353 : }
354 0 : aOldV.SetPos( nPos );
355 0 : rSet.Put( aOldV );
356 0 : }
357 : }
358 0 : break;
359 : default:
360 0 : break;
361 : }
362 :
363 0 : if( bNewFrms )
364 0 : rFmt.MakeFrms();
365 :
366 0 : return MAKEFRMS;
367 : }
368 :
369 : static bool
370 0 : lcl_SetFlyFrmAttr(SwDoc & rDoc,
371 : sal_Int8 (SwDoc::*pSetFlyFrmAnchor)(SwFrmFmt &, SfxItemSet &, bool),
372 : SwFrmFmt & rFlyFmt, SfxItemSet & rSet)
373 : {
374 : // #i32968# Inserting columns in the frame causes MakeFrmFmt to put two
375 : // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
376 0 : ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
377 :
378 : // Is the anchor attribute included?
379 : // If so, we pass it to a special method, which returns sal_True
380 : // if the Fly needs to be created anew, because we e.g change the FlyType.
381 : sal_Int8 const nMakeFrms =
382 0 : (SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, false ))
383 0 : ? (rDoc.*pSetFlyFrmAnchor)( rFlyFmt, rSet, false )
384 0 : : DONTMAKEFRMS;
385 :
386 : const SfxPoolItem* pItem;
387 0 : SfxItemIter aIter( rSet );
388 0 : SfxItemSet aTmpSet( rDoc.GetAttrPool(), aFrmFmtSetRange );
389 0 : sal_uInt16 nWhich = aIter.GetCurItem()->Which();
390 0 : do {
391 0 : switch( nWhich )
392 : {
393 : case RES_FILL_ORDER:
394 : case RES_BREAK:
395 : case RES_PAGEDESC:
396 : case RES_CNTNT:
397 : case RES_FOOTER:
398 : OSL_FAIL( "Unknown Fly attribute." );
399 : // no break;
400 : case RES_CHAIN:
401 0 : rSet.ClearItem( nWhich );
402 0 : break;
403 : case RES_ANCHOR:
404 0 : if( DONTMAKEFRMS != nMakeFrms )
405 0 : break;
406 :
407 : default:
408 0 : if( !IsInvalidItem( aIter.GetCurItem() ) && ( SFX_ITEM_SET !=
409 0 : rFlyFmt.GetAttrSet().GetItemState( nWhich, true, &pItem ) ||
410 0 : *pItem != *aIter.GetCurItem() ))
411 0 : aTmpSet.Put( *aIter.GetCurItem() );
412 0 : break;
413 : }
414 :
415 0 : if( aIter.IsAtEnd() )
416 0 : break;
417 :
418 0 : } while( 0 != ( nWhich = aIter.NextItem()->Which() ) );
419 :
420 0 : if( aTmpSet.Count() )
421 0 : rFlyFmt.SetFmtAttr( aTmpSet );
422 :
423 0 : if( MAKEFRMS == nMakeFrms )
424 0 : rFlyFmt.MakeFrms();
425 :
426 0 : return aTmpSet.Count() || MAKEFRMS == nMakeFrms;
427 : }
428 :
429 0 : void SwDoc::CheckForUniqueItemForLineFillNameOrIndex(SfxItemSet& rSet)
430 : {
431 0 : SdrModel* pDrawModel = GetOrCreateDrawModel();
432 0 : SfxItemIter aIter(rSet);
433 :
434 0 : for(const SfxPoolItem* pItem = aIter.FirstItem(); pItem; pItem = aIter.NextItem())
435 : {
436 0 : const SfxPoolItem* pResult = pItem;
437 :
438 0 : switch(pItem->Which())
439 : {
440 : case XATTR_FILLBITMAP:
441 : {
442 0 : pResult = static_cast< const XFillBitmapItem* >(pItem)->checkForUniqueItem(pDrawModel);
443 0 : break;
444 : }
445 : case XATTR_LINEDASH:
446 : {
447 0 : pResult = static_cast< const XLineDashItem* >(pItem)->checkForUniqueItem(pDrawModel);
448 0 : break;
449 : }
450 : case XATTR_LINESTART:
451 : {
452 0 : pResult = static_cast< const XLineStartItem* >(pItem)->checkForUniqueItem(pDrawModel);
453 0 : break;
454 : }
455 : case XATTR_LINEEND:
456 : {
457 0 : pResult = static_cast< const XLineEndItem* >(pItem)->checkForUniqueItem(pDrawModel);
458 0 : break;
459 : }
460 : case XATTR_FILLGRADIENT:
461 : {
462 0 : pResult = static_cast< const XFillGradientItem* >(pItem)->checkForUniqueItem(pDrawModel);
463 0 : break;
464 : }
465 : case XATTR_FILLFLOATTRANSPARENCE:
466 : {
467 0 : pResult = static_cast< const XFillFloatTransparenceItem* >(pItem)->checkForUniqueItem(pDrawModel);
468 0 : break;
469 : }
470 : case XATTR_FILLHATCH:
471 : {
472 0 : pResult = static_cast< const XFillHatchItem* >(pItem)->checkForUniqueItem(pDrawModel);
473 0 : break;
474 : }
475 : }
476 :
477 0 : if(pResult != pItem)
478 : {
479 0 : rSet.Put(*pResult);
480 0 : delete pResult;
481 : }
482 0 : }
483 0 : }
484 :
485 0 : bool SwDoc::SetFlyFrmAttr( SwFrmFmt& rFlyFmt, SfxItemSet& rSet )
486 : {
487 0 : if( !rSet.Count() )
488 0 : return false;
489 :
490 0 : boost::scoped_ptr<SwUndoFmtAttrHelper> pSaveUndo;
491 :
492 0 : if (GetIDocumentUndoRedo().DoesUndo())
493 : {
494 0 : GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it
495 0 : pSaveUndo.reset( new SwUndoFmtAttrHelper( rFlyFmt ) );
496 : }
497 :
498 : //UUUU Need to check for unique item for DrawingLayer items of type NameOrIndex
499 : // and evtl. correct that item to ensure unique names for that type. This call may
500 : // modify/correct entries inside of the given SfxItemSet
501 0 : CheckForUniqueItemForLineFillNameOrIndex(rSet);
502 :
503 : bool const bRet =
504 0 : lcl_SetFlyFrmAttr(*this, &SwDoc::SetFlyFrmAnchor, rFlyFmt, rSet);
505 :
506 0 : if ( pSaveUndo.get() )
507 : {
508 0 : if ( pSaveUndo->GetUndo() )
509 : {
510 0 : GetIDocumentUndoRedo().AppendUndo( pSaveUndo->ReleaseUndo() );
511 : }
512 : }
513 :
514 0 : SetModified();
515 :
516 0 : return bRet;
517 : }
518 :
519 : // #i73249#
520 0 : void SwDoc::SetFlyFrmTitle( SwFlyFrmFmt& rFlyFrmFmt,
521 : const OUString& sNewTitle )
522 : {
523 0 : if ( rFlyFrmFmt.GetObjTitle() == sNewTitle )
524 : {
525 0 : return;
526 : }
527 :
528 0 : ::sw::DrawUndoGuard const drawUndoGuard(GetIDocumentUndoRedo());
529 :
530 0 : if (GetIDocumentUndoRedo().DoesUndo())
531 : {
532 0 : GetIDocumentUndoRedo().AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt,
533 : UNDO_FLYFRMFMT_TITLE,
534 : rFlyFrmFmt.GetObjTitle(),
535 0 : sNewTitle ) );
536 : }
537 :
538 0 : rFlyFrmFmt.SetObjTitle( sNewTitle, true );
539 :
540 0 : SetModified();
541 : }
542 :
543 0 : void SwDoc::SetFlyFrmDescription( SwFlyFrmFmt& rFlyFrmFmt,
544 : const OUString& sNewDescription )
545 : {
546 0 : if ( rFlyFrmFmt.GetObjDescription() == sNewDescription )
547 : {
548 0 : return;
549 : }
550 :
551 0 : ::sw::DrawUndoGuard const drawUndoGuard(GetIDocumentUndoRedo());
552 :
553 0 : if (GetIDocumentUndoRedo().DoesUndo())
554 : {
555 0 : GetIDocumentUndoRedo().AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt,
556 : UNDO_FLYFRMFMT_DESCRIPTION,
557 : rFlyFrmFmt.GetObjDescription(),
558 0 : sNewDescription ) );
559 : }
560 :
561 0 : rFlyFrmFmt.SetObjDescription( sNewDescription, true );
562 :
563 0 : SetModified();
564 : }
565 :
566 0 : bool SwDoc::SetFrmFmtToFly( SwFrmFmt& rFmt, SwFrmFmt& rNewFmt,
567 : SfxItemSet* pSet, bool bKeepOrient )
568 : {
569 0 : bool bChgAnchor = false, bFrmSz = false;
570 :
571 0 : const SwFmtFrmSize aFrmSz( rFmt.GetFrmSize() );
572 0 : const SwFmtVertOrient aVert( rFmt.GetVertOrient() );
573 0 : const SwFmtHoriOrient aHori( rFmt.GetHoriOrient() );
574 :
575 0 : SwUndoSetFlyFmt* pUndo = 0;
576 0 : bool const bUndo = GetIDocumentUndoRedo().DoesUndo();
577 0 : if (bUndo)
578 : {
579 0 : pUndo = new SwUndoSetFlyFmt( rFmt, rNewFmt );
580 0 : GetIDocumentUndoRedo().AppendUndo(pUndo);
581 : }
582 :
583 : // #i32968# Inserting columns in the section causes MakeFrmFmt to put
584 : // 2 objects of type SwUndoFrmFmt on the undo stack. We don't want them.
585 0 : ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
586 :
587 : // Set the column first, or we'll have trouble with
588 : //Set/Reset/Synch. and so on
589 : const SfxPoolItem* pItem;
590 0 : if( SFX_ITEM_SET != rNewFmt.GetAttrSet().GetItemState( RES_COL ))
591 0 : rFmt.ResetFmtAttr( RES_COL );
592 :
593 0 : if( rFmt.DerivedFrom() != &rNewFmt )
594 : {
595 0 : rFmt.SetDerivedFrom( &rNewFmt );
596 :
597 : // 1. If not automatic = ignore; else = dispose
598 : // 2. Dispose of it!
599 0 : if( SFX_ITEM_SET == rNewFmt.GetAttrSet().GetItemState( RES_FRM_SIZE, false ))
600 : {
601 0 : rFmt.ResetFmtAttr( RES_FRM_SIZE );
602 0 : bFrmSz = true;
603 : }
604 :
605 0 : const SfxItemSet* pAsk = pSet;
606 0 : if( !pAsk ) pAsk = &rNewFmt.GetAttrSet();
607 0 : if( SFX_ITEM_SET == pAsk->GetItemState( RES_ANCHOR, false, &pItem )
608 0 : && ((SwFmtAnchor*)pItem)->GetAnchorId() !=
609 0 : rFmt.GetAnchor().GetAnchorId() )
610 : {
611 0 : if( pSet )
612 0 : bChgAnchor = MAKEFRMS == SetFlyFrmAnchor( rFmt, *pSet, false );
613 : else
614 : {
615 : // Needs to have the FlyFmt range, because we set attributes in it,
616 : // in SetFlyFrmAnchor.
617 0 : SfxItemSet aFlySet( *rNewFmt.GetAttrSet().GetPool(),
618 0 : rNewFmt.GetAttrSet().GetRanges() );
619 0 : aFlySet.Put( *pItem );
620 0 : bChgAnchor = MAKEFRMS == SetFlyFrmAnchor( rFmt, aFlySet, false);
621 : }
622 : }
623 : }
624 :
625 : // Only reset vertical and horizontal orientation, if we have automatic alignment
626 : // set in the template. Otherwise use the old value.
627 : // If we update the frame template the Fly should NOT lose its orientation (which
628 : // is not being updated!).
629 : // text::HoriOrientation::NONE and text::VertOrientation::NONE are allowed now
630 0 : if (!bKeepOrient)
631 : {
632 0 : rFmt.ResetFmtAttr(RES_VERT_ORIENT);
633 0 : rFmt.ResetFmtAttr(RES_HORI_ORIENT);
634 : }
635 :
636 0 : rFmt.ResetFmtAttr( RES_PRINT, RES_SURROUND );
637 0 : rFmt.ResetFmtAttr( RES_LR_SPACE, RES_UL_SPACE );
638 0 : rFmt.ResetFmtAttr( RES_BACKGROUND, RES_COL );
639 0 : rFmt.ResetFmtAttr( RES_URL, RES_EDIT_IN_READONLY );
640 :
641 0 : if( !bFrmSz )
642 0 : rFmt.SetFmtAttr( aFrmSz );
643 :
644 0 : if( bChgAnchor )
645 0 : rFmt.MakeFrms();
646 :
647 0 : if( pUndo )
648 0 : pUndo->DeRegisterFromFormat( rFmt );
649 :
650 0 : SetModified();
651 :
652 0 : return bChgAnchor;
653 : }
654 :
655 0 : void SwDoc::GetGrfNms( const SwFlyFrmFmt& rFmt, OUString* pGrfName,
656 : OUString* pFltName ) const
657 : {
658 0 : SwNodeIndex aIdx( *rFmt.GetCntnt().GetCntntIdx(), 1 );
659 0 : const SwGrfNode* pGrfNd = aIdx.GetNode().GetGrfNode();
660 0 : if( pGrfNd && pGrfNd->IsLinkedFile() )
661 0 : pGrfNd->GetFileFilterNms( pGrfName, pFltName );
662 0 : }
663 :
664 0 : bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
665 : RndStdIds _eAnchorType,
666 : const bool _bSameOnly,
667 : const bool _bPosCorr )
668 : {
669 : OSL_ENSURE( GetCurrentLayout(), "No layout!" );
670 :
671 0 : if ( !_rMrkList.GetMarkCount() ||
672 0 : _rMrkList.GetMark( 0 )->GetMarkedSdrObj()->GetUpGroup() )
673 : {
674 0 : return false;
675 : }
676 :
677 0 : GetIDocumentUndoRedo().StartUndo( UNDO_INSATTR, NULL );
678 :
679 0 : bool bUnmark = false;
680 0 : for ( sal_uInt16 i = 0; i < _rMrkList.GetMarkCount(); ++i )
681 : {
682 0 : SdrObject* pObj = _rMrkList.GetMark( i )->GetMarkedSdrObj();
683 0 : if ( !pObj->ISA(SwVirtFlyDrawObj) )
684 : {
685 0 : SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
686 :
687 : // consider, that drawing object has
688 : // no user call. E.g.: a 'virtual' drawing object is disconnected by
689 : // the anchor type change of the 'master' drawing object.
690 : // Continue with next selected object and assert, if this isn't excepted.
691 0 : if ( !pContact )
692 : {
693 : #if OSL_DEBUG_LEVEL > 0
694 : bool bNoUserCallExcepted =
695 : pObj->ISA(SwDrawVirtObj) &&
696 : !static_cast<SwDrawVirtObj*>(pObj)->IsConnected();
697 : OSL_ENSURE( bNoUserCallExcepted, "SwDoc::ChgAnchor(..) - no contact at selected drawing object" );
698 : #endif
699 0 : continue;
700 : }
701 :
702 : // #i26791#
703 0 : const SwFrm* pOldAnchorFrm = pContact->GetAnchorFrm( pObj );
704 0 : const SwFrm* pNewAnchorFrm = pOldAnchorFrm;
705 :
706 : // #i54336#
707 : // Instead of only keeping the index position for an as-character
708 : // anchored object the complete <SwPosition> is kept, because the
709 : // anchor index position could be moved, if the object again is
710 : // anchored as character.
711 0 : boost::scoped_ptr<const SwPosition> xOldAsCharAnchorPos;
712 0 : const RndStdIds eOldAnchorType = pContact->GetAnchorId();
713 0 : if ( !_bSameOnly && eOldAnchorType == FLY_AS_CHAR )
714 : {
715 0 : xOldAsCharAnchorPos.reset(new SwPosition(pContact->GetCntntAnchor()));
716 : }
717 :
718 0 : if ( _bSameOnly )
719 0 : _eAnchorType = eOldAnchorType;
720 :
721 0 : SwFmtAnchor aNewAnch( _eAnchorType );
722 0 : Rectangle aObjRect( pContact->GetAnchoredObj( pObj )->GetObjRect().SVRect() );
723 0 : const Point aPt( aObjRect.TopLeft() );
724 :
725 0 : switch ( _eAnchorType )
726 : {
727 : case FLY_AT_PARA:
728 : case FLY_AT_CHAR:
729 : {
730 0 : const Point aNewPoint = ( pOldAnchorFrm->IsVertical() ||
731 0 : pOldAnchorFrm->IsRightToLeft() )
732 : ? aObjRect.TopRight()
733 0 : : aPt;
734 :
735 : // allow drawing objects in header/footer
736 0 : pNewAnchorFrm = ::FindAnchor( pOldAnchorFrm, aNewPoint, false );
737 0 : if ( pNewAnchorFrm->IsTxtFrm() && ((SwTxtFrm*)pNewAnchorFrm)->IsFollow() )
738 : {
739 0 : pNewAnchorFrm = ((SwTxtFrm*)pNewAnchorFrm)->FindMaster();
740 : }
741 0 : if ( pNewAnchorFrm->IsProtected() )
742 : {
743 0 : pNewAnchorFrm = 0;
744 : }
745 : else
746 : {
747 0 : SwPosition aPos( *((SwCntntFrm*)pNewAnchorFrm)->GetNode() );
748 0 : aNewAnch.SetType( _eAnchorType );
749 0 : aNewAnch.SetAnchor( &aPos );
750 : }
751 : }
752 0 : break;
753 :
754 : case FLY_AT_FLY: // LAYER_IMPL
755 : {
756 : // Search the closest SwFlyFrm starting from the upper left corner.
757 : SwFrm *pTxtFrm;
758 : {
759 0 : SwCrsrMoveState aState( MV_SETONLYTEXT );
760 0 : SwPosition aPos( GetNodes() );
761 0 : Point aPoint( aPt );
762 0 : aPoint.setX(aPoint.getX() - 1);
763 0 : GetCurrentLayout()->GetCrsrOfst( &aPos, aPoint, &aState );
764 : // consider that drawing objects can be in
765 : // header/footer. Thus, <GetFrm()> by left-top-corner
766 0 : pTxtFrm = aPos.nNode.GetNode().
767 0 : GetCntntNode()->getLayoutFrm( GetCurrentLayout(), &aPt, 0, false );
768 : }
769 0 : const SwFrm *pTmp = ::FindAnchor( pTxtFrm, aPt );
770 0 : pNewAnchorFrm = pTmp->FindFlyFrm();
771 0 : if( pNewAnchorFrm && !pNewAnchorFrm->IsProtected() )
772 : {
773 0 : const SwFrmFmt *pTmpFmt = ((SwFlyFrm*)pNewAnchorFrm)->GetFmt();
774 0 : const SwFmtCntnt& rCntnt = pTmpFmt->GetCntnt();
775 0 : SwPosition aPos( *rCntnt.GetCntntIdx() );
776 0 : aNewAnch.SetAnchor( &aPos );
777 0 : break;
778 : }
779 :
780 0 : aNewAnch.SetType( FLY_AT_PAGE );
781 : // no break
782 : }
783 : case FLY_AT_PAGE:
784 : {
785 0 : pNewAnchorFrm = GetCurrentLayout()->Lower();
786 0 : while ( pNewAnchorFrm && !pNewAnchorFrm->Frm().IsInside( aPt ) )
787 0 : pNewAnchorFrm = pNewAnchorFrm->GetNext();
788 0 : if ( !pNewAnchorFrm )
789 0 : continue;
790 :
791 0 : aNewAnch.SetPageNum( ((SwPageFrm*)pNewAnchorFrm)->GetPhyPageNum());
792 : }
793 0 : break;
794 : case FLY_AS_CHAR:
795 0 : if( _bSameOnly ) // Change of position/size
796 : {
797 0 : if( !pOldAnchorFrm )
798 : {
799 0 : pContact->ConnectToLayout();
800 0 : pOldAnchorFrm = pContact->GetAnchorFrm();
801 : }
802 0 : ((SwTxtFrm*)pOldAnchorFrm)->Prepare();
803 : }
804 : else // Change of anchors
805 : {
806 : // allow drawing objects in header/footer
807 0 : pNewAnchorFrm = ::FindAnchor( pOldAnchorFrm, aPt, false );
808 0 : if( pNewAnchorFrm->IsProtected() )
809 : {
810 0 : pNewAnchorFrm = 0;
811 0 : break;
812 : }
813 :
814 0 : bUnmark = ( 0 != i );
815 0 : Point aPoint( aPt );
816 0 : aPoint.setX(aPoint.getX() - 1); // Do not load in the DrawObj!
817 0 : aNewAnch.SetType( FLY_AS_CHAR );
818 0 : SwPosition aPos( *((SwCntntFrm*)pNewAnchorFrm)->GetNode() );
819 0 : if ( pNewAnchorFrm->Frm().IsInside( aPoint ) )
820 : {
821 : // We need to find a TextNode, because only there we can anchor a
822 : // content-bound DrawObject.
823 0 : SwCrsrMoveState aState( MV_SETONLYTEXT );
824 0 : GetCurrentLayout()->GetCrsrOfst( &aPos, aPoint, &aState );
825 : }
826 : else
827 : {
828 : SwCntntNode &rCNd = (SwCntntNode&)
829 0 : *((SwCntntFrm*)pNewAnchorFrm)->GetNode();
830 0 : if ( pNewAnchorFrm->Frm().Bottom() < aPt.Y() )
831 0 : rCNd.MakeStartIndex( &aPos.nContent );
832 : else
833 0 : rCNd.MakeEndIndex( &aPos.nContent );
834 : }
835 0 : aNewAnch.SetAnchor( &aPos );
836 0 : SetAttr( aNewAnch, *pContact->GetFmt() );
837 : // #i26791# - adjust vertical positioning to 'center to
838 : // baseline'
839 0 : SetAttr( SwFmtVertOrient( 0, text::VertOrientation::CENTER, text::RelOrientation::FRAME ), *pContact->GetFmt() );
840 0 : SwTxtNode *pNd = aPos.nNode.GetNode().GetTxtNode();
841 : OSL_ENSURE( pNd, "Cursor not positioned at TxtNode." );
842 :
843 0 : SwFmtFlyCnt aFmt( pContact->GetFmt() );
844 0 : pNd->InsertItem( aFmt, aPos.nContent.GetIndex(), 0 );
845 : }
846 0 : break;
847 : default:
848 : OSL_ENSURE( !this, "unexpected AnchorId." );
849 : }
850 :
851 0 : if ( (FLY_AS_CHAR != _eAnchorType) &&
852 0 : pNewAnchorFrm &&
853 0 : ( !_bSameOnly || pNewAnchorFrm != pOldAnchorFrm ) )
854 : {
855 : // #i26791# - Direct object positioning no longer needed. Apply
856 : // of attributes (method call <SetAttr(..)>) takes care of the
857 : // invalidation of the object position.
858 0 : SetAttr( aNewAnch, *pContact->GetFmt() );
859 0 : if ( _bPosCorr )
860 : {
861 : // #i33313# - consider not connected 'virtual' drawing
862 : // objects
863 0 : if ( pObj->ISA(SwDrawVirtObj) &&
864 0 : !static_cast<SwDrawVirtObj*>(pObj)->IsConnected() )
865 : {
866 0 : SwRect aNewObjRect( aObjRect );
867 0 : static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( 0L ))
868 : ->AdjustPositioningAttr( pNewAnchorFrm,
869 0 : &aNewObjRect );
870 : }
871 : else
872 : {
873 0 : static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( pObj ))
874 0 : ->AdjustPositioningAttr( pNewAnchorFrm );
875 : }
876 : }
877 : }
878 :
879 : // #i54336#
880 0 : if (xOldAsCharAnchorPos)
881 : {
882 0 : if ( pNewAnchorFrm)
883 : {
884 : // We need to handle InCntnts in a special way:
885 : // The TxtAttribut needs to be destroyed which, unfortunately, also
886 : // destroys the format. To avoid that, we disconnect the format from
887 : // the attribute.
888 0 : const sal_Int32 nIndx( xOldAsCharAnchorPos->nContent.GetIndex() );
889 0 : SwTxtNode* pTxtNode( xOldAsCharAnchorPos->nNode.GetNode().GetTxtNode() );
890 : OSL_ENSURE( pTxtNode, "<SwDoc::ChgAnchor(..)> - missing previous anchor text node for as-character anchored object" );
891 : OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
892 : SwTxtAttr * const pHnt =
893 0 : pTxtNode->GetTxtAttrForCharAt( nIndx, RES_TXTATR_FLYCNT );
894 0 : const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
895 :
896 : // They are disconnected. We now have to destroy the attribute.
897 0 : pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIndx, nIndx );
898 : }
899 0 : }
900 : }
901 : }
902 :
903 0 : GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
904 0 : SetModified();
905 :
906 0 : return bUnmark;
907 : }
908 :
909 0 : int SwDoc::Chainable( const SwFrmFmt &rSource, const SwFrmFmt &rDest )
910 : {
911 : // The Source must not yet have a Follow.
912 0 : const SwFmtChain &rOldChain = rSource.GetChain();
913 0 : if ( rOldChain.GetNext() )
914 0 : return SW_CHAIN_SOURCE_CHAINED;
915 :
916 : // Target must not be equal to Source and we also must not have a closed chain.
917 0 : const SwFrmFmt *pFmt = &rDest;
918 0 : do {
919 0 : if( pFmt == &rSource )
920 0 : return SW_CHAIN_SELF;
921 0 : pFmt = pFmt->GetChain().GetNext();
922 : } while ( pFmt );
923 :
924 : // There must not be a chaining from outside to inside or the other way around.
925 0 : if( rDest.IsLowerOf( rSource ) || rSource .IsLowerOf( rDest ) )
926 0 : return SW_CHAIN_SELF;
927 :
928 : // The Target must not yet have a Master.
929 0 : const SwFmtChain &rChain = rDest.GetChain();
930 0 : if( rChain.GetPrev() )
931 0 : return SW_CHAIN_IS_IN_CHAIN;
932 :
933 : // Target must be empty.
934 0 : const SwNodeIndex* pCntIdx = rDest.GetCntnt().GetCntntIdx();
935 0 : if( !pCntIdx )
936 0 : return SW_CHAIN_NOT_FOUND;
937 :
938 0 : SwNodeIndex aNxtIdx( *pCntIdx, 1 );
939 0 : const SwTxtNode* pTxtNd = aNxtIdx.GetNode().GetTxtNode();
940 0 : if( !pTxtNd )
941 0 : return SW_CHAIN_NOT_FOUND;
942 :
943 0 : const sal_uLong nFlySttNd = pCntIdx->GetIndex();
944 0 : if( 2 != ( pCntIdx->GetNode().EndOfSectionIndex() - nFlySttNd ) ||
945 0 : pTxtNd->GetTxt().getLength() )
946 : {
947 0 : return SW_CHAIN_NOT_EMPTY;
948 : }
949 :
950 0 : sal_uInt16 nArrLen = GetSpzFrmFmts()->size();
951 0 : for( sal_uInt16 n = 0; n < nArrLen; ++n )
952 : {
953 0 : const SwFmtAnchor& rAnchor = (*GetSpzFrmFmts())[ n ]->GetAnchor();
954 : sal_uLong nTstSttNd;
955 : // #i20622# - to-frame anchored objects are allowed.
956 0 : if ( ((rAnchor.GetAnchorId() == FLY_AT_PARA) ||
957 0 : (rAnchor.GetAnchorId() == FLY_AT_CHAR)) &&
958 0 : 0 != rAnchor.GetCntntAnchor() &&
959 : nFlySttNd <= ( nTstSttNd =
960 0 : rAnchor.GetCntntAnchor()->nNode.GetIndex() ) &&
961 0 : nTstSttNd < nFlySttNd + 2 )
962 : {
963 0 : return SW_CHAIN_NOT_EMPTY;
964 : }
965 : }
966 :
967 : // We also need to consider the right area.
968 : // Both Flys need to be located in the same area (Body, Header/Footer, Fly).
969 : // If the Source is not the selected frame, it's enough to find a suitable
970 : // one. e.g. if it's requested by the API.
971 :
972 : // both in the same fly, header, footer or on the page?
973 0 : const SwFmtAnchor &rSrcAnchor = rSource.GetAnchor(),
974 0 : &rDstAnchor = rDest.GetAnchor();
975 0 : sal_uLong nEndOfExtras = GetNodes().GetEndOfExtras().GetIndex();
976 0 : bool bAllowed = false;
977 0 : if ( FLY_AT_PAGE == rSrcAnchor.GetAnchorId() )
978 : {
979 0 : if ( (FLY_AT_PAGE == rDstAnchor.GetAnchorId()) ||
980 0 : ( rDstAnchor.GetCntntAnchor() &&
981 0 : rDstAnchor.GetCntntAnchor()->nNode.GetIndex() > nEndOfExtras ))
982 0 : bAllowed = true;
983 : }
984 0 : else if( rSrcAnchor.GetCntntAnchor() && rDstAnchor.GetCntntAnchor() )
985 : {
986 0 : const SwNodeIndex &rSrcIdx = rSrcAnchor.GetCntntAnchor()->nNode,
987 0 : &rDstIdx = rDstAnchor.GetCntntAnchor()->nNode;
988 0 : const SwStartNode* pSttNd = 0;
989 0 : if( rSrcIdx == rDstIdx ||
990 0 : ( !pSttNd &&
991 0 : 0 != ( pSttNd = rSrcIdx.GetNode().FindFlyStartNode() ) &&
992 0 : pSttNd == rDstIdx.GetNode().FindFlyStartNode() ) ||
993 0 : ( !pSttNd &&
994 0 : 0 != ( pSttNd = rSrcIdx.GetNode().FindFooterStartNode() ) &&
995 0 : pSttNd == rDstIdx.GetNode().FindFooterStartNode() ) ||
996 0 : ( !pSttNd &&
997 0 : 0 != ( pSttNd = rSrcIdx.GetNode().FindHeaderStartNode() ) &&
998 0 : pSttNd == rDstIdx.GetNode().FindHeaderStartNode() ) ||
999 0 : ( !pSttNd && rDstIdx.GetIndex() > nEndOfExtras &&
1000 0 : rSrcIdx.GetIndex() > nEndOfExtras ))
1001 0 : bAllowed = true;
1002 : }
1003 :
1004 0 : return bAllowed ? SW_CHAIN_OK : SW_CHAIN_WRONG_AREA;
1005 : }
1006 :
1007 0 : int SwDoc::Chain( SwFrmFmt &rSource, const SwFrmFmt &rDest )
1008 : {
1009 0 : int nErr = Chainable( rSource, rDest );
1010 0 : if ( !nErr )
1011 : {
1012 0 : GetIDocumentUndoRedo().StartUndo( UNDO_CHAINE, NULL );
1013 :
1014 0 : SwFlyFrmFmt& rDestFmt = (SwFlyFrmFmt&)rDest;
1015 :
1016 : // Attach Follow to the Master.
1017 0 : SwFmtChain aChain = rDestFmt.GetChain();
1018 0 : aChain.SetPrev( &(SwFlyFrmFmt&)rSource );
1019 0 : SetAttr( aChain, rDestFmt );
1020 :
1021 0 : SfxItemSet aSet( GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE,
1022 0 : RES_CHAIN, RES_CHAIN, 0 );
1023 :
1024 : // Attach Follow to the Master.
1025 0 : aChain.SetPrev( &(SwFlyFrmFmt&)rSource );
1026 0 : SetAttr( aChain, rDestFmt );
1027 :
1028 : // Attach Master to the Follow.
1029 : // Make sure that the Master has a fixed height.
1030 0 : aChain = rSource.GetChain();
1031 0 : aChain.SetNext( &rDestFmt );
1032 0 : aSet.Put( aChain );
1033 :
1034 0 : SwFmtFrmSize aSize( rSource.GetFrmSize() );
1035 0 : if ( aSize.GetHeightSizeType() != ATT_FIX_SIZE )
1036 : {
1037 0 : SwFlyFrm *pFly = SwIterator<SwFlyFrm,SwFmt>::FirstElement( rSource );
1038 0 : if ( pFly )
1039 0 : aSize.SetHeight( pFly->Frm().Height() );
1040 0 : aSize.SetHeightSizeType( ATT_FIX_SIZE );
1041 0 : aSet.Put( aSize );
1042 : }
1043 0 : SetAttr( aSet, rSource );
1044 :
1045 0 : GetIDocumentUndoRedo().EndUndo( UNDO_CHAINE, NULL );
1046 : }
1047 0 : return nErr;
1048 : }
1049 :
1050 0 : void SwDoc::Unchain( SwFrmFmt &rFmt )
1051 : {
1052 0 : SwFmtChain aChain( rFmt.GetChain() );
1053 0 : if ( aChain.GetNext() )
1054 : {
1055 0 : GetIDocumentUndoRedo().StartUndo( UNDO_UNCHAIN, NULL );
1056 0 : SwFrmFmt *pFollow = aChain.GetNext();
1057 0 : aChain.SetNext( 0 );
1058 0 : SetAttr( aChain, rFmt );
1059 0 : aChain = pFollow->GetChain();
1060 0 : aChain.SetPrev( 0 );
1061 0 : SetAttr( aChain, *pFollow );
1062 0 : GetIDocumentUndoRedo().EndUndo( UNDO_UNCHAIN, NULL );
1063 0 : }
1064 0 : }
1065 :
1066 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|