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