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