1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: docfly.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <svtools/itemiter.hxx>
37 #include <svx/svdobj.hxx>
38 #include <svx/svdpage.hxx>
39 #include <svx/svdmodel.hxx>
40 #include <svx/svdocapt.hxx>
41 #include <svx/svdmark.hxx>
42 #include <fmtfsize.hxx>
43 #include <fmtornt.hxx>
44 #include <fmtsrnd.hxx>
45 #include <dcontact.hxx>
49 #include <ndindex.hxx>
51 #include <fmtcntnt.hxx>
52 #include <fmtanchr.hxx>
53 #include <txtflcnt.hxx>
54 #include <fmtflcnt.hxx>
56 #include <pagefrm.hxx>
57 #include <rootfrm.hxx>
58 #include <flyfrms.hxx>
59 #include <frmtool.hxx>
65 #include <swtable.hxx>
66 #include <crstate.hxx>
68 #include <fmtcnct.hxx>
69 #include <dflyobj.hxx>
71 // --> OD 2009-07-20 #i73249#
72 #include <undoflystrattr.hxx>
75 extern USHORT
GetHtmlMode( const SwDocShell
* );
78 using namespace ::com::sun::star
;
80 /*-----------------17.02.98 08:35-------------------
82 --------------------------------------------------*/
83 USHORT
SwDoc::GetFlyCount( FlyCntType eType
) const
85 const SwSpzFrmFmts
& rFmts
= *GetSpzFrmFmts();
86 USHORT nSize
= rFmts
.Count();
88 const SwNodeIndex
* pIdx
;
89 for ( USHORT i
= 0; i
< nSize
; i
++)
91 const SwFrmFmt
* pFlyFmt
= rFmts
[ i
];
92 if( RES_FLYFRMFMT
== pFlyFmt
->Which()
93 && 0 != ( pIdx
= pFlyFmt
->GetCntnt().GetCntntIdx() )
94 && pIdx
->GetNodes().IsDocNodes()
97 const SwNode
* pNd
= GetNodes()[ pIdx
->GetIndex() + 1 ];
102 if(!pNd
->IsNoTxtNode())
107 if( pNd
->IsGrfNode() )
124 /*-----------------17.02.98 08:35-------------------
126 --------------------------------------------------*/
127 // If you change this, also update SwXFrameEnumeration in unocoll.
128 SwFrmFmt
* SwDoc::GetFlyNum( USHORT nIdx
, FlyCntType eType
)
130 SwSpzFrmFmts
& rFmts
= *GetSpzFrmFmts();
131 SwFrmFmt
* pRetFmt
= 0;
132 USHORT nSize
= rFmts
.Count();
133 const SwNodeIndex
* pIdx
;
135 for( USHORT i
= 0; !pRetFmt
&& i
< nSize
; ++i
)
137 SwFrmFmt
* pFlyFmt
= rFmts
[ i
];
138 if( RES_FLYFRMFMT
== pFlyFmt
->Which()
139 && 0 != ( pIdx
= pFlyFmt
->GetCntnt().GetCntntIdx() )
140 && pIdx
->GetNodes().IsDocNodes()
143 const SwNode
* pNd
= GetNodes()[ pIdx
->GetIndex() + 1 ];
147 if( !pNd
->IsNoTxtNode() && nIdx
== nCount
++)
151 if(pNd
->IsGrfNode() && nIdx
== nCount
++ )
155 if(pNd
->IsOLENode() && nIdx
== nCount
++)
169 /***********************************************************************
171 #* Methode : SetFlyFrmAnchor
172 #* Beschreibung: Das Ankerattribut des FlyFrms aendert sich.
173 #* Datum : MA 01. Feb. 94
174 #* Update : JP 09.03.98
175 #***********************************************************************/
177 Point
lcl_FindAnchorLayPos( SwDoc
& rDoc
, const SwFmtAnchor
& rAnch
,
178 const SwFrmFmt
* pFlyFmt
)
181 if( rDoc
.GetRootFrm() )
182 switch( rAnch
.GetAnchorId() )
185 if( pFlyFmt
&& rAnch
.GetCntntAnchor() )
187 const SwFrm
* pOld
= ((SwFlyFrmFmt
*)pFlyFmt
)->GetFrm( &aRet
, FALSE
);
189 aRet
= pOld
->Frm().Pos();
194 case FLY_AUTO_CNTNT
: // LAYER_IMPL
195 if( rAnch
.GetCntntAnchor() )
197 const SwPosition
*pPos
= rAnch
.GetCntntAnchor();
198 const SwCntntNode
* pNd
= pPos
->nNode
.GetNode().GetCntntNode();
199 const SwFrm
* pOld
= pNd
? pNd
->GetFrm( &aRet
, 0, FALSE
) : 0;
201 aRet
= pOld
->Frm().Pos();
205 case FLY_AT_FLY
: // LAYER_IMPL
206 if( rAnch
.GetCntntAnchor() )
208 const SwFlyFrmFmt
* pFmt
= (SwFlyFrmFmt
*)rAnch
.GetCntntAnchor()->
209 nNode
.GetNode().GetFlyFmt();
210 const SwFrm
* pOld
= pFmt
? pFmt
->GetFrm( &aRet
, FALSE
) : 0;
212 aRet
= pOld
->Frm().Pos();
218 USHORT nPgNum
= rAnch
.GetPageNum();
219 const SwPageFrm
*pPage
= (SwPageFrm
*)rDoc
.GetRootFrm()->Lower();
220 for( USHORT i
= 1; (i
<= nPgNum
) && pPage
; ++i
,
221 pPage
= (const SwPageFrm
*)pPage
->GetNext() )
224 aRet
= pPage
->Frm().Pos();
236 #define IGNOREANCHOR 1
237 #define DONTMAKEFRMS 2
239 sal_Int8
SwDoc::SetFlyFrmAnchor( SwFrmFmt
& rFmt
, SfxItemSet
& rSet
, BOOL bNewFrms
)
241 //Ankerwechsel sind fast immer in alle 'Richtungen' erlaubt.
242 //Ausnahme: Absatz- bzw. Zeichengebundene Rahmen duerfen wenn sie in
243 //Kopf-/Fusszeilen stehen nicht Seitengebunden werden.
244 const SwFmtAnchor
&rOldAnch
= rFmt
.GetAnchor();
245 const RndStdIds nOld
= rOldAnch
.GetAnchorId();
247 SwFmtAnchor
aNewAnch( (SwFmtAnchor
&)rSet
.Get( RES_ANCHOR
) );
248 RndStdIds nNew
= aNewAnch
.GetAnchorId();
250 // ist der neue ein gueltiger Anker?
251 if( !aNewAnch
.GetCntntAnchor() && (FLY_AT_FLY
== nNew
||
252 FLY_AT_CNTNT
== nNew
|| FLY_IN_CNTNT
== nNew
||
253 FLY_AUTO_CNTNT
== nNew
))
260 Point
aOldAnchorPos( ::lcl_FindAnchorLayPos( *this, rOldAnch
, &rFmt
));
261 Point
aNewAnchorPos( ::lcl_FindAnchorLayPos( *this, aNewAnch
, 0 ));
263 //Die alten Frms vernichten. Dabei werden die Views implizit gehidet und
264 //doppeltes hiden waere so eine art Show!
267 if( FLY_IN_CNTNT
== nOld
)
269 //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
270 //werden. Leider reisst dies neben den Frms auch noch das Format mit
271 //in sein Grab. Um dass zu unterbinden loesen wir vorher die
272 //Verbindung zwischen Attribut und Format.
273 const SwPosition
*pPos
= rOldAnch
.GetCntntAnchor();
274 SwTxtNode
*pTxtNode
= pPos
->nNode
.GetNode().GetTxtNode();
275 ASSERT( pTxtNode
->HasHints(), "Missing FlyInCnt-Hint." );
276 const xub_StrLen nIdx
= pPos
->nContent
.GetIndex();
277 SwTxtAttr
* const pHnt
=
278 pTxtNode
->GetTxtAttrForCharAt( nIdx
, RES_TXTATR_FLYCNT
);
279 ASSERT( pHnt
&& pHnt
->Which() == RES_TXTATR_FLYCNT
,
280 "Missing FlyInCnt-Hint." );
281 ASSERT( pHnt
&& pHnt
->GetFlyCnt().GetFrmFmt() == &rFmt
,
282 "Wrong TxtFlyCnt-Hint." );
283 const_cast<SwFmtFlyCnt
&>(pHnt
->GetFlyCnt()).SetFlyFmt();
285 //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
287 pTxtNode
->DeleteAttributes( RES_TXTATR_FLYCNT
, nIdx
, nIdx
);
290 //Endlich kann das Attribut gesetzt werden. Es muss das erste Attribut
291 //sein; Undo depends on it!
292 rFmt
.SetFmtAttr( aNewAnch
);
294 //Positionskorrekturen
295 const SfxPoolItem
* pItem
;
299 //Wenn keine Positionsattribute hereinkommen, dann muss dafuer
300 //gesorgt werden, das keine unerlaubte automatische Ausrichtung
303 const SwPosition
*pPos
= aNewAnch
.GetCntntAnchor();
304 SwTxtNode
*pNd
= pPos
->nNode
.GetNode().GetTxtNode();
305 ASSERT( pNd
, "Crsr steht nicht auf TxtNode." );
307 SwFmtFlyCnt
aFmt( static_cast<SwFlyFrmFmt
*>(&rFmt
) );
308 pNd
->InsertItem( aFmt
, pPos
->nContent
.GetIndex(), 0 );
311 if( SFX_ITEM_SET
!= rSet
.GetItemState( RES_VERT_ORIENT
, FALSE
, &pItem
))
313 SwFmtVertOrient
aOldV( rFmt
.GetVertOrient() );
315 switch( aOldV
.GetVertOrient() )
317 case text::VertOrientation::LINE_TOP
: aOldV
.SetVertOrient( text::VertOrientation::TOP
); break;
318 case text::VertOrientation::LINE_CENTER
: aOldV
.SetVertOrient( text::VertOrientation::CENTER
); break;
319 case text::VertOrientation::LINE_BOTTOM
: aOldV
.SetVertOrient( text::VertOrientation::BOTTOM
); break;
320 case text::VertOrientation::NONE
: aOldV
.SetVertOrient( text::VertOrientation::CENTER
); break;
330 case FLY_AUTO_CNTNT
: // LAYER_IMPL
331 case FLY_AT_FLY
: // LAYER_IMPL
334 //Wenn keine Positionsattribute hereinschneien korrigieren wir
335 //die Position so, dass die Dokumentkoordinaten des Flys erhalten
337 //Chg: Wenn sich in den Positionsattributen lediglich die
338 //Ausrichtung veraendert (text::RelOrientation::FRAME vs. text::RelOrientation::PRTAREA), dann wird die
339 //Position ebenfalls korrigiert.
340 if( SFX_ITEM_SET
!= rSet
.GetItemState( RES_HORI_ORIENT
, FALSE
, &pItem
))
343 SwFmtHoriOrient
aOldH( rFmt
.GetHoriOrient() );
345 if( text::HoriOrientation::NONE
== aOldH
.GetHoriOrient() && ( !pItem
||
346 aOldH
.GetPos() == ((SwFmtHoriOrient
*)pItem
)->GetPos() ))
348 SwTwips nPos
= FLY_IN_CNTNT
== nOld
? 0 : aOldH
.GetPos();
349 nPos
+= aOldAnchorPos
.X() - aNewAnchorPos
.X();
353 SwFmtHoriOrient
* pH
= (SwFmtHoriOrient
*)pItem
;
354 aOldH
.SetHoriOrient( pH
->GetHoriOrient() );
355 aOldH
.SetRelationOrient( pH
->GetRelationOrient() );
357 aOldH
.SetPos( nPos
);
361 if( SFX_ITEM_SET
!= rSet
.GetItemState( RES_VERT_ORIENT
, FALSE
, &pItem
))
363 SwFmtVertOrient
aOldV( rFmt
.GetVertOrient() );
365 // OD 2004-05-14 #i28922# - correction: compare <aOldV.GetVertOrient()
366 // with <text::VertOrientation::NONE>
367 if( text::VertOrientation::NONE
== aOldV
.GetVertOrient() && (!pItem
||
368 aOldV
.GetPos() == ((SwFmtVertOrient
*)pItem
)->GetPos() ) )
370 SwTwips nPos
= FLY_IN_CNTNT
== nOld
? 0 : aOldV
.GetPos();
371 nPos
+= aOldAnchorPos
.Y() - aNewAnchorPos
.Y();
374 SwFmtVertOrient
* pV
= (SwFmtVertOrient
*)pItem
;
375 aOldV
.SetVertOrient( pV
->GetVertOrient() );
376 aOldV
.SetRelationOrient( pV
->GetRelationOrient() );
378 aOldV
.SetPos( nPos
);
393 BOOL
SwDoc::SetFlyFrmAttr( SwFrmFmt
& rFlyFmt
, SfxItemSet
& rSet
)
398 ::std::auto_ptr
<SwUndoFmtAttrHelper
> pSaveUndo
;
399 const bool bDoesUndo
= DoesUndo();
404 pSaveUndo
.reset( new SwUndoFmtAttrHelper( rFlyFmt
) );
405 // --> FME 2004-10-13 #i32968#
406 // Inserting columns in the frame causes MakeFrmFmt to put two
407 // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
412 //Ist das Ankerattribut dabei? Falls ja ueberlassen wir die Verarbeitung
413 //desselben einer Spezialmethode. Sie Returnt TRUE wenn der Fly neu
414 //erzeugt werden muss (z.B. weil ein Wechsel des FlyTyps vorliegt).
415 sal_Int8 nMakeFrms
= SFX_ITEM_SET
== rSet
.GetItemState( RES_ANCHOR
, FALSE
)?
416 SetFlyFrmAnchor( rFlyFmt
, rSet
, FALSE
) : DONTMAKEFRMS
;
418 const SfxPoolItem
* pItem
;
419 SfxItemIter
aIter( rSet
);
420 SfxItemSet
aTmpSet( GetAttrPool(), aFrmFmtSetRange
);
421 USHORT nWhich
= aIter
.GetCurItem()->Which();
430 ASSERT( !this, ":-) Unbekanntes Attribut fuer Fly." );
433 rSet
.ClearItem( nWhich
);
436 if( DONTMAKEFRMS
!= nMakeFrms
)
440 if( !IsInvalidItem( aIter
.GetCurItem() ) && ( SFX_ITEM_SET
!=
441 rFlyFmt
.GetAttrSet().GetItemState( nWhich
, TRUE
, &pItem
) ||
442 *pItem
!= *aIter
.GetCurItem() ))
443 aTmpSet
.Put( *aIter
.GetCurItem() );
447 if( aIter
.IsAtEnd() )
450 } while( 0 != ( nWhich
= aIter
.NextItem()->Which() ) );
452 if( aTmpSet
.Count() )
453 rFlyFmt
.SetFmtAttr( aTmpSet
);
455 if( MAKEFRMS
== nMakeFrms
)
458 if ( pSaveUndo
.get() )
460 // --> FME 2004-10-13 #i32968#
464 if ( pSaveUndo
->GetUndo() )
466 AppendUndo( pSaveUndo
->ReleaseUndo() );
472 return aTmpSet
.Count() || MAKEFRMS
== nMakeFrms
;
475 // --> OD 2009-07-20 #i73249#
476 void SwDoc::SetFlyFrmTitle( SwFlyFrmFmt
& rFlyFrmFmt
,
477 const String
& sNewTitle
)
479 if ( rFlyFrmFmt
.GetObjTitle() == sNewTitle
)
484 const bool bFormerIsNoDrawUndoObj( IsNoDrawUndoObj() );
485 SetNoDrawUndoObj( true );
490 AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt
,
491 UNDO_FLYFRMFMT_TITLE
,
492 rFlyFrmFmt
.GetObjTitle(),
496 rFlyFrmFmt
.SetObjTitle( sNewTitle
, true );
498 SetNoDrawUndoObj( bFormerIsNoDrawUndoObj
);
503 void SwDoc::SetFlyFrmDescription( SwFlyFrmFmt
& rFlyFrmFmt
,
504 const String
& sNewDescription
)
506 if ( rFlyFrmFmt
.GetObjDescription() == sNewDescription
)
511 const bool bFormerIsNoDrawUndoObj( IsNoDrawUndoObj() );
512 SetNoDrawUndoObj( true );
517 AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt
,
518 UNDO_FLYFRMFMT_DESCRIPTION
,
519 rFlyFrmFmt
.GetObjDescription(),
523 rFlyFrmFmt
.SetObjDescription( sNewDescription
, true );
525 SetNoDrawUndoObj( bFormerIsNoDrawUndoObj
);
531 /***************************************************************************
532 * Methode : BOOL SwDoc::SetFrmFmtToFly( SwFlyFrm&, SwFrmFmt& )
534 * Erstellt : OK 14.04.94 15:40
535 * Aenderung : JP 23.04.98
536 ***************************************************************************/
538 BOOL
SwDoc::SetFrmFmtToFly( SwFrmFmt
& rFmt
, SwFrmFmt
& rNewFmt
,
539 SfxItemSet
* pSet
, BOOL bKeepOrient
)
541 BOOL bChgAnchor
= FALSE
, bFrmSz
= FALSE
;
543 const SwFmtFrmSize
aFrmSz( rFmt
.GetFrmSize() );
544 const SwFmtVertOrient
aVert( rFmt
.GetVertOrient() );
545 const SwFmtHoriOrient
aHori( rFmt
.GetHoriOrient() );
547 SwUndoSetFlyFmt
* pUndo
= 0;
551 AppendUndo( pUndo
= new SwUndoSetFlyFmt( rFmt
, rNewFmt
) );
552 // --> FME 2004-10-13 #i32968#
553 // Inserting columns in the section causes MakeFrmFmt to put two
554 // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
559 //Erstmal die Spalten setzen, sonst gibts nix als Aerger mit dem
560 //Set/Reset/Abgleich usw.
561 const SfxPoolItem
* pItem
;
562 if( SFX_ITEM_SET
!= rNewFmt
.GetAttrSet().GetItemState( RES_COL
))
563 rFmt
.ResetFmtAttr( RES_COL
);
565 if( rFmt
.DerivedFrom() != &rNewFmt
)
567 rFmt
.SetDerivedFrom( &rNewFmt
);
569 // 1. wenn nicht automatisch -> ignorieren, sonst -> wech
570 // 2. wech damit, MB!
571 if( SFX_ITEM_SET
== rNewFmt
.GetAttrSet().GetItemState( RES_FRM_SIZE
, FALSE
))
573 rFmt
.ResetFmtAttr( RES_FRM_SIZE
);
577 const SfxItemSet
* pAsk
= pSet
;
578 if( !pAsk
) pAsk
= &rNewFmt
.GetAttrSet();
579 if( SFX_ITEM_SET
== pAsk
->GetItemState( RES_ANCHOR
, FALSE
, &pItem
)
580 && ((SwFmtAnchor
*)pItem
)->GetAnchorId() !=
581 rFmt
.GetAnchor().GetAnchorId() )
584 bChgAnchor
= MAKEFRMS
== SetFlyFrmAnchor( rFmt
, *pSet
, FALSE
);
587 //JP 23.04.98: muss den FlyFmt-Range haben, denn im SetFlyFrmAnchor
588 // werden Attribute in diesen gesetzt!
589 SfxItemSet
aFlySet( *rNewFmt
.GetAttrSet().GetPool(),
590 rNewFmt
.GetAttrSet().GetRanges() );
591 aFlySet
.Put( *pItem
);
592 bChgAnchor
= MAKEFRMS
== SetFlyFrmAnchor( rFmt
, aFlySet
, FALSE
);
597 //Hori und Vert nur dann resetten, wenn in der Vorlage eine
598 //automatische Ausrichtung eingestellt ist, anderfalls den alten Wert
599 //wieder hineinstopfen.
600 //JP 09.06.98: beim Update der RahmenVorlage sollte der Fly NICHT
601 // seine Orientierng verlieren (diese wird nicht geupdatet!)
602 //OS: #96584# text::HoriOrientation::NONE and text::VertOrientation::NONE are allowed now
605 rFmt
.ResetFmtAttr(RES_VERT_ORIENT
);
606 rFmt
.ResetFmtAttr(RES_HORI_ORIENT
);
609 rFmt
.ResetFmtAttr( RES_PRINT
, RES_SURROUND
);
610 rFmt
.ResetFmtAttr( RES_LR_SPACE
, RES_UL_SPACE
);
611 rFmt
.ResetFmtAttr( RES_BACKGROUND
, RES_COL
);
612 rFmt
.ResetFmtAttr( RES_URL
, RES_EDIT_IN_READONLY
);
615 rFmt
.SetFmtAttr( aFrmSz
);
621 rFmt
.Remove( pUndo
);
625 // --> FME 2004-10-13 #i32968#
633 void SwDoc::GetGrfNms( const SwFlyFrmFmt
& rFmt
, String
* pGrfName
,
634 String
* pFltName
) const
636 SwNodeIndex
aIdx( *rFmt
.GetCntnt().GetCntntIdx(), 1 );
637 const SwGrfNode
* pGrfNd
= aIdx
.GetNode().GetGrfNode();
638 if( pGrfNd
&& pGrfNd
->IsLinkedFile() )
639 pGrfNd
->GetFileFilterNms( pGrfName
, pFltName
);
642 /*************************************************************************
644 |* SwDoc::ChgAnchor()
646 |* Ersterstellung MA 10. Jan. 95
647 |* Letzte Aenderung JP 08.07.98
649 *************************************************************************/
651 sal_Bool
SwDoc::ChgAnchor( const SdrMarkList
& _rMrkList
,
652 RndStdIds _eAnchorType
,
653 const sal_Bool _bSameOnly
,
654 const sal_Bool _bPosCorr
)
656 ASSERT( GetRootFrm(), "Ohne Layout geht gar nichts" );
658 if ( !_rMrkList
.GetMarkCount() ||
659 _rMrkList
.GetMark( 0 )->GetMarkedSdrObj()->GetUpGroup() )
664 StartUndo( UNDO_INSATTR
, NULL
);
666 BOOL bUnmark
= FALSE
;
667 for ( USHORT i
= 0; i
< _rMrkList
.GetMarkCount(); ++i
)
669 SdrObject
* pObj
= _rMrkList
.GetMark( i
)->GetMarkedSdrObj();
670 if ( !pObj
->ISA(SwVirtFlyDrawObj
) )
672 SwDrawContact
* pContact
= static_cast<SwDrawContact
*>(GetUserCall(pObj
));
674 // OD 27.06.2003 #108784# - consider, that drawing object has
675 // no user call. E.g.: a 'virtual' drawing object is disconnected by
676 // the anchor type change of the 'master' drawing object.
677 // Continue with next selected object and assert, if this isn't excepted.
681 bool bNoUserCallExcepted
=
682 pObj
->ISA(SwDrawVirtObj
) &&
683 !static_cast<SwDrawVirtObj
*>(pObj
)->IsConnected();
684 ASSERT( bNoUserCallExcepted
, "SwDoc::ChgAnchor(..) - no contact at selected drawing object" );
689 // OD 2004-03-29 #i26791#
690 const SwFrm
* pOldAnchorFrm
= pContact
->GetAnchorFrm( pObj
);
691 const SwFrm
* pNewAnchorFrm
= pOldAnchorFrm
;
693 // --> OD 2006-03-01 #i54336#
694 // Instead of only keeping the index position for an as-character
695 // anchored object the complete <SwPosition> is kept, because the
696 // anchor index position could be moved, if the object again is
697 // anchored as character.
698 // xub_StrLen nIndx = STRING_NOTFOUND;
699 const SwPosition
* pOldAsCharAnchorPos( 0L );
700 const RndStdIds eOldAnchorType
= pContact
->GetAnchorId();
701 if ( !_bSameOnly
&& eOldAnchorType
== FLY_IN_CNTNT
)
703 pOldAsCharAnchorPos
= new SwPosition( pContact
->GetCntntAnchor() );
708 _eAnchorType
= eOldAnchorType
;
710 SwFmtAnchor
aNewAnch( _eAnchorType
);
711 Rectangle
aObjRect( pContact
->GetAnchoredObj( pObj
)->GetObjRect().SVRect() );
712 const Point
aPt( aObjRect
.TopLeft() );
714 switch ( _eAnchorType
)
719 const Point aNewPoint
= pOldAnchorFrm
&&
720 ( pOldAnchorFrm
->IsVertical() ||
721 pOldAnchorFrm
->IsRightToLeft() )
722 ? aObjRect
.TopRight()
725 // OD 18.06.2003 #108784# - allow drawing objects in header/footer
726 pNewAnchorFrm
= ::FindAnchor( pOldAnchorFrm
, aNewPoint
, false );
727 if ( pNewAnchorFrm
->IsTxtFrm() && ((SwTxtFrm
*)pNewAnchorFrm
)->IsFollow() )
729 pNewAnchorFrm
= ((SwTxtFrm
*)pNewAnchorFrm
)->FindMaster();
731 if ( pNewAnchorFrm
->IsProtected() )
737 SwPosition
aPos( *((SwCntntFrm
*)pNewAnchorFrm
)->GetNode() );
738 aNewAnch
.SetType( _eAnchorType
);
739 aNewAnch
.SetAnchor( &aPos
);
744 case FLY_AT_FLY
: // LAYER_IMPL
746 //Ausgehend von der linken oberen Ecke des Fly den
747 //dichtesten SwFlyFrm suchen.
750 SwCrsrMoveState
aState( MV_SETONLYTEXT
);
751 SwPosition
aPos( GetNodes() );
754 GetRootFrm()->GetCrsrOfst( &aPos
, aPoint
, &aState
);
755 // OD 20.06.2003 #108784# - consider that drawing objects
756 // can be in header/footer. Thus, <GetFrm()> by left-top-corner
757 pTxtFrm
= aPos
.nNode
.GetNode().
758 GetCntntNode()->GetFrm( &aPt
, 0, FALSE
);
760 const SwFrm
*pTmp
= ::FindAnchor( pTxtFrm
, aPt
);
761 pNewAnchorFrm
= pTmp
->FindFlyFrm();
762 if( pNewAnchorFrm
&& !pNewAnchorFrm
->IsProtected() )
764 const SwFrmFmt
*pTmpFmt
= ((SwFlyFrm
*)pNewAnchorFrm
)->GetFmt();
765 const SwFmtCntnt
& rCntnt
= pTmpFmt
->GetCntnt();
766 SwPosition
aPos( *rCntnt
.GetCntntIdx() );
767 aNewAnch
.SetAnchor( &aPos
);
771 aNewAnch
.SetType( FLY_PAGE
);
776 pNewAnchorFrm
= GetRootFrm()->Lower();
777 while ( pNewAnchorFrm
&& !pNewAnchorFrm
->Frm().IsInside( aPt
) )
778 pNewAnchorFrm
= pNewAnchorFrm
->GetNext();
779 if ( !pNewAnchorFrm
)
782 aNewAnch
.SetPageNum( ((SwPageFrm
*)pNewAnchorFrm
)->GetPhyPageNum());
786 if( _bSameOnly
) // Positions/Groessenaenderung
790 pContact
->ConnectToLayout();
791 pOldAnchorFrm
= pContact
->GetAnchorFrm();
793 ((SwTxtFrm
*)pOldAnchorFrm
)->Prepare();
797 // OD 18.06.2003 #108784# - allow drawing objects in header/footer
798 pNewAnchorFrm
= ::FindAnchor( pOldAnchorFrm
, aPt
, false );
799 if( pNewAnchorFrm
->IsProtected() )
805 bUnmark
= ( 0 != i
);
807 aPoint
.X() -= 1; // nicht im DrawObj landen!!
808 aNewAnch
.SetType( FLY_IN_CNTNT
);
809 SwPosition
aPos( *((SwCntntFrm
*)pNewAnchorFrm
)->GetNode() );
810 if ( pNewAnchorFrm
->Frm().IsInside( aPoint
) )
812 // es muss ein TextNode gefunden werden, denn nur dort
813 // ist ein inhaltsgebundenes DrawObjekt zu verankern
814 SwCrsrMoveState
aState( MV_SETONLYTEXT
);
815 GetRootFrm()->GetCrsrOfst( &aPos
, aPoint
, &aState
);
819 SwCntntNode
&rCNd
= (SwCntntNode
&)
820 *((SwCntntFrm
*)pNewAnchorFrm
)->GetNode();
821 if ( pNewAnchorFrm
->Frm().Bottom() < aPt
.Y() )
822 rCNd
.MakeStartIndex( &aPos
.nContent
);
824 rCNd
.MakeEndIndex( &aPos
.nContent
);
826 aNewAnch
.SetAnchor( &aPos
);
827 SetAttr( aNewAnch
, *pContact
->GetFmt() );
828 // OD 2004-04-13 #i26791# - adjust vertical positioning to
829 // 'center to baseline'
830 SetAttr( SwFmtVertOrient( 0, text::VertOrientation::CENTER
, text::RelOrientation::FRAME
), *pContact
->GetFmt() );
831 SwTxtNode
*pNd
= aPos
.nNode
.GetNode().GetTxtNode();
832 ASSERT( pNd
, "Cursor not positioned at TxtNode." );
834 SwFmtFlyCnt
aFmt( pContact
->GetFmt() );
835 pNd
->InsertItem( aFmt
, aPos
.nContent
.GetIndex(), 0 );
839 ASSERT( !this, "unexpected AnchorId." );
842 if ( (FLY_IN_CNTNT
!= _eAnchorType
) &&
844 ( !_bSameOnly
|| pNewAnchorFrm
!= pOldAnchorFrm
) )
846 // OD 2004-04-06 #i26791# - Direct object positioning no longer
847 // needed. Apply of attributes (method call <SetAttr(..)>) takes
848 // care of the invalidation of the object position.
849 SetAttr( aNewAnch
, *pContact
->GetFmt() );
852 // --> OD 2004-08-24 #i33313# - consider not connected
853 // 'virtual' drawing objects
854 if ( pObj
->ISA(SwDrawVirtObj
) &&
855 !static_cast<SwDrawVirtObj
*>(pObj
)->IsConnected() )
857 SwRect
aNewObjRect( aObjRect
);
858 static_cast<SwAnchoredDrawObject
*>(pContact
->GetAnchoredObj( 0L ))
859 ->AdjustPositioningAttr( pNewAnchorFrm
,
865 static_cast<SwAnchoredDrawObject
*>(pContact
->GetAnchoredObj( pObj
))
866 ->AdjustPositioningAttr( pNewAnchorFrm
);
871 // --> OD 2006-03-01 #i54336#
872 if ( pNewAnchorFrm
&& pOldAsCharAnchorPos
)
874 //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
875 //werden. Leider reisst dies neben den Frms auch noch das Format mit
876 //in sein Grab. Um dass zu unterbinden loesen wir vorher die
877 //Verbindung zwischen Attribut und Format.
878 const xub_StrLen
nIndx( pOldAsCharAnchorPos
->nContent
.GetIndex() );
879 SwTxtNode
* pTxtNode( pOldAsCharAnchorPos
->nNode
.GetNode().GetTxtNode() );
880 ASSERT( pTxtNode
, "<SwDoc::ChgAnchor(..)> - missing previous anchor text node for as-character anchored object" );
881 ASSERT( pTxtNode
->HasHints(), "Missing FlyInCnt-Hint." );
882 SwTxtAttr
* const pHnt
=
883 pTxtNode
->GetTxtAttrForCharAt( nIndx
, RES_TXTATR_FLYCNT
);
884 const_cast<SwFmtFlyCnt
&>(pHnt
->GetFlyCnt()).SetFlyFmt();
886 //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
888 pTxtNode
->DeleteAttributes( RES_TXTATR_FLYCNT
, nIndx
, nIndx
);
889 delete pOldAsCharAnchorPos
;
895 EndUndo( UNDO_END
, NULL
);
902 /* -----------------23.07.98 13:56-------------------
904 * --------------------------------------------------*/
905 int SwDoc::Chainable( const SwFrmFmt
&rSource
, const SwFrmFmt
&rDest
)
907 //Die Source darf noch keinen Follow haben.
908 const SwFmtChain
&rOldChain
= rSource
.GetChain();
909 if ( rOldChain
.GetNext() )
910 return SW_CHAIN_SOURCE_CHAINED
;
912 //Ziel darf natuerlich nicht gleich Source sein und es
913 //darf keine geschlossene Kette entstehen.
914 const SwFrmFmt
*pFmt
= &rDest
;
916 if( pFmt
== &rSource
)
917 return SW_CHAIN_SELF
;
918 pFmt
= pFmt
->GetChain().GetNext();
921 //Auch eine Verkettung von Innen nach aussen oder von aussen
922 //nach innen ist nicht zulaessig.
923 if( rDest
.IsLowerOf( rSource
) || rSource
.IsLowerOf( rDest
) )
924 return SW_CHAIN_SELF
;
926 //Das Ziel darf noch keinen Master haben.
927 const SwFmtChain
&rChain
= rDest
.GetChain();
928 if( rChain
.GetPrev() )
929 return SW_CHAIN_IS_IN_CHAIN
;
931 //Das Ziel muss leer sein.
932 const SwNodeIndex
* pCntIdx
= rDest
.GetCntnt().GetCntntIdx();
934 return SW_CHAIN_NOT_FOUND
;
936 SwNodeIndex
aNxtIdx( *pCntIdx
, 1 );
937 const SwTxtNode
* pTxtNd
= aNxtIdx
.GetNode().GetTxtNode();
939 return SW_CHAIN_NOT_FOUND
;
941 const ULONG nFlySttNd
= pCntIdx
->GetIndex();
942 if( 2 != ( pCntIdx
->GetNode().EndOfSectionIndex() - nFlySttNd
) ||
943 pTxtNd
->GetTxt().Len() )
944 return SW_CHAIN_NOT_EMPTY
;
946 USHORT nArrLen
= GetSpzFrmFmts()->Count();
947 for( USHORT n
= 0; n
< nArrLen
; ++n
)
949 const SwFmtAnchor
& rAnchor
= (*GetSpzFrmFmts())[ n
]->GetAnchor();
951 // OD 11.12.2003 #i20622# - to-frame anchored objects are allowed.
952 if ( ( rAnchor
.GetAnchorId() == FLY_AT_CNTNT
||
953 rAnchor
.GetAnchorId() == FLY_AUTO_CNTNT
) &&
954 0 != rAnchor
.GetCntntAnchor() &&
955 nFlySttNd
<= ( nTstSttNd
=
956 rAnchor
.GetCntntAnchor()->nNode
.GetIndex() ) &&
957 nTstSttNd
< nFlySttNd
+ 2 )
959 return SW_CHAIN_NOT_EMPTY
;
963 //Auf die richtige Area muessen wir auch noch einen Blick werfen.
964 //Beide Flys muessen im selben Bereich (Body, Head/Foot, Fly) sitzen
965 //Wenn die Source nicht der selektierte Rahmen ist, so reicht es
966 //Wenn ein passender gefunden wird (Der Wunsch kann z.B. von der API
969 // both in the same fly, header, footer or on the page?
970 const SwFmtAnchor
&rSrcAnchor
= rSource
.GetAnchor(),
971 &rDstAnchor
= rDest
.GetAnchor();
972 ULONG nEndOfExtras
= GetNodes().GetEndOfExtras().GetIndex();
973 BOOL bAllowed
= FALSE
;
974 if( FLY_PAGE
== rSrcAnchor
.GetAnchorId() )
976 if( FLY_PAGE
== rDstAnchor
.GetAnchorId() ||
977 ( rDstAnchor
.GetCntntAnchor() &&
978 rDstAnchor
.GetCntntAnchor()->nNode
.GetIndex() > nEndOfExtras
))
981 else if( rSrcAnchor
.GetCntntAnchor() && rDstAnchor
.GetCntntAnchor() )
983 const SwNodeIndex
&rSrcIdx
= rSrcAnchor
.GetCntntAnchor()->nNode
,
984 &rDstIdx
= rDstAnchor
.GetCntntAnchor()->nNode
;
985 const SwStartNode
* pSttNd
= 0;
986 if( rSrcIdx
== rDstIdx
||
988 0 != ( pSttNd
= rSrcIdx
.GetNode().FindFlyStartNode() ) &&
989 pSttNd
== rDstIdx
.GetNode().FindFlyStartNode() ) ||
991 0 != ( pSttNd
= rSrcIdx
.GetNode().FindFooterStartNode() ) &&
992 pSttNd
== rDstIdx
.GetNode().FindFooterStartNode() ) ||
994 0 != ( pSttNd
= rSrcIdx
.GetNode().FindHeaderStartNode() ) &&
995 pSttNd
== rDstIdx
.GetNode().FindHeaderStartNode() ) ||
996 ( !pSttNd
&& rDstIdx
.GetIndex() > nEndOfExtras
&&
997 rSrcIdx
.GetIndex() > nEndOfExtras
))
1001 return bAllowed
? SW_CHAIN_OK
: SW_CHAIN_WRONG_AREA
;
1003 /* -----------------23.07.98 13:56-------------------
1005 * --------------------------------------------------*/
1006 int SwDoc::Chain( SwFrmFmt
&rSource
, const SwFrmFmt
&rDest
)
1008 int nErr
= Chainable( rSource
, rDest
);
1011 StartUndo( UNDO_CHAINE
, NULL
);
1013 SwFlyFrmFmt
& rDestFmt
= (SwFlyFrmFmt
&)rDest
;
1015 //Follow an den Master haengen.
1016 SwFmtChain aChain
= rDestFmt
.GetChain();
1017 aChain
.SetPrev( &(SwFlyFrmFmt
&)rSource
);
1018 SetAttr( aChain
, rDestFmt
);
1020 SfxItemSet
aSet( GetAttrPool(), RES_FRM_SIZE
, RES_FRM_SIZE
,
1021 RES_CHAIN
, RES_CHAIN
, 0 );
1023 //Follow an den Master haengen.
1024 aChain
.SetPrev( &(SwFlyFrmFmt
&)rSource
);
1025 SetAttr( aChain
, rDestFmt
);
1027 //Master an den Follow haengen und dafuer sorgen, dass der Master
1028 //eine fixierte Hoehe hat.
1029 aChain
= rSource
.GetChain();
1030 aChain
.SetNext( &rDestFmt
);
1033 SwFmtFrmSize
aSize( rSource
.GetFrmSize() );
1034 if ( aSize
.GetHeightSizeType() != ATT_FIX_SIZE
)
1036 SwClientIter
aIter( rSource
);
1037 SwFlyFrm
*pFly
= (SwFlyFrm
*)aIter
.First( TYPE(SwFlyFrm
) );
1039 aSize
.SetHeight( pFly
->Frm().Height() );
1040 aSize
.SetHeightSizeType( ATT_FIX_SIZE
);
1043 SetAttr( aSet
, rSource
);
1045 EndUndo( UNDO_CHAINE
, NULL
);
1049 /* -----------------23.07.98 13:56-------------------
1051 * --------------------------------------------------*/
1052 void SwDoc::Unchain( SwFrmFmt
&rFmt
)
1054 SwFmtChain
aChain( rFmt
.GetChain() );
1055 if ( aChain
.GetNext() )
1057 StartUndo( UNDO_UNCHAIN
, NULL
);
1058 SwFrmFmt
*pFollow
= aChain
.GetNext();
1059 aChain
.SetNext( 0 );
1060 SetAttr( aChain
, rFmt
);
1061 aChain
= pFollow
->GetChain();
1062 aChain
.SetPrev( 0 );
1063 SetAttr( aChain
, *pFollow
);
1064 EndUndo( UNDO_UNCHAIN
, NULL
);