merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / txtnode / atrflyin.cxx
blob92cbc614d663e9fa7a6d6c97bff0ad0575dab9f6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: atrflyin.cxx,v $
10 * $Revision: 1.10 $
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"
36 #include "hintids.hxx"
37 #include "cntfrm.hxx" // _GetFly
38 #include "doc.hxx"
39 #include "pam.hxx" // fuer SwTxtFlyCnt
40 #include "flyfrm.hxx" // fuer SwTxtFlyCnt
41 #include "ndtxt.hxx" // SwFlyFrmFmt
42 #include "frmfmt.hxx" // SwFlyFrmFmt
43 #include <fmtflcnt.hxx>
44 #include <txtflcnt.hxx>
45 #include <fmtanchr.hxx>
46 #include "swfont.hxx"
47 #include "txtfrm.hxx"
48 #include "flyfrms.hxx"
49 // --> OD 2004-11-09 #i26945#
50 #include <objectformatter.hxx>
51 // <--
53 SwFmtFlyCnt::SwFmtFlyCnt( SwFrmFmt *pFrmFmt )
54 : SfxPoolItem( RES_TXTATR_FLYCNT ),
55 pTxtAttr( 0 ),
56 pFmt( pFrmFmt )
60 int __EXPORT SwFmtFlyCnt::operator==( const SfxPoolItem& rAttr ) const
62 ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
63 return( pTxtAttr && ((SwFmtFlyCnt&)rAttr).pTxtAttr &&
64 *pTxtAttr->GetStart() == *((SwFmtFlyCnt&)rAttr).pTxtAttr->GetStart() &&
65 pFmt == ((SwFmtFlyCnt&)rAttr).GetFrmFmt() );
68 SfxPoolItem* __EXPORT SwFmtFlyCnt::Clone( SfxItemPool* ) const
70 return new SwFmtFlyCnt( pFmt );
73 SwTxtFlyCnt::SwTxtFlyCnt( SwFmtFlyCnt& rAttr, xub_StrLen nStartPos )
74 : SwTxtAttr( rAttr, nStartPos )
76 rAttr.pTxtAttr = this;
77 SetHasDummyChar(true);
82 /*************************************************************************
83 * SwTxtFlyCnt::MakeTxtHint()
85 * An dieser Stelle soll einmal der Gesamtzusammenhang bei der Erzeugung
86 * eines neuen SwTxtFlyCnt erlaeutert werden.
87 * Das MakeTxtHint() wird z.B. im SwTxtNode::Copy() gerufen.
88 * Fuer die komplette Verdopplung sind folgende Schritte notwendig:
89 * 1) Duplizieren des pFmt incl. Inhalt, Attributen etc.
90 * 2) Setzen des Ankers
91 * 3) Benachrichtigung
92 * Da fuer die Bewaeltigung der Aufgaben nicht immer alle Informationen
93 * bereitstehen und darueber hinaus bestimmte Methoden erst zu einem
94 * spaeteren Zeitpunkt gerufen werden duerfen (weil nocht nicht alle
95 * Nodeinformationen vorliegen), verteilt sich der Ablauf.
96 * ad 1) MakeTxtHint() wird durch den Aufruf von SwDoc::CopyLayout()
97 * der das neue FlyFrmFmt erzeugt und mit dem duplizierten Inhalt des
98 * FlyFrm verbunden.
99 * ad 2) SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
100 * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
101 * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
102 * werden, da der Zielnode unbestimmt ist.
103 * ad 3) _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
104 * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
105 * gefunden, so wird ein neuer FlyFrm angelegt.
106 * Kritisch an diesem Vorgehen ist, dass das pCntnt->AppendFly() eine
107 * sofortige Neuformatierung von pCntnt anstoesst. Die Rekursion kommt
108 * allerdings durch den Lockmechanismus in SwTxtFrm::Format() nicht
109 * zu stande.
110 * Attraktiv ist der Umstand, dass niemand ueber die vom Node abhaengigen
111 * CntntFrms iterieren braucht, um die FlyInCntFrm anzulegen. Dies geschieht
112 * bei der Arbeit.
113 *************************************************************************/
115 void SwTxtFlyCnt::CopyFlyFmt( SwDoc* pDoc )
117 SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
118 ASSERT( pFmt, "von welchem Format soll ich eine Kopie erzeugen?" )
119 // Das FlyFrmFmt muss dupliziert werden.
120 // In CopyLayoutFmt (siehe doclay.cxx) wird das FlyFrmFmt erzeugt
121 // und der Inhalt dupliziert.
123 // fuers kopieren vom Attribut das Undo immer abschalten
124 BOOL bUndo = pDoc->DoesUndo();
125 pDoc->DoUndo( FALSE );
126 SwFmtAnchor aAnchor( pFmt->GetAnchor() );
127 if( FLY_PAGE != aAnchor.GetAnchorId() &&
128 pDoc != pFmt->GetDoc() ) // Unterschiedliche Docs?
130 // JP 03.06.96: dann sorge dafuer, das der koperierte Anker auf
131 // gueltigen Content zeigt! Die Umsetzung auf die
132 // richtige Position erfolgt spaeter.
133 SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), +2 );
134 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
135 if( !pCNd )
136 pCNd = pDoc->GetNodes().GoNext( &aIdx );
138 SwPosition* pPos = (SwPosition*)aAnchor.GetCntntAnchor();
139 pPos->nNode = aIdx;
140 if( FLY_IN_CNTNT == aAnchor.GetAnchorId() )
141 pPos->nContent.Assign( pCNd, 0 );
142 else
144 pPos->nContent.Assign( 0, 0 );
145 ASSERT( !this, "CopyFlyFmt: Was fuer ein Anker?" );
149 SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
150 pDoc->DoUndo( bUndo );
151 ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
154 /*************************************************************************
155 * SwTxtFlyCnt::SetAnchor()
157 * SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
158 * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
159 * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
160 * werden, da der Zielnode unbestimmt ist.
161 * (siehe Kommentar in SwTxtFlyCnt::MakeTxtHint)
162 *************************************************************************/
164 void SwTxtFlyCnt::SetAnchor( const SwTxtNode *pNode )
166 // fuers Undo muss der neue Anker schon bekannt sein !
168 // Wir ermitteln den Index im Nodesarray zum Node
170 SwDoc* pDoc = (SwDoc*)pNode->GetDoc();
172 SwIndex aIdx( (SwTxtNode*)pNode, *GetStart() );
173 SwPosition aPos( *pNode->StartOfSectionNode(), aIdx );
174 SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
175 SwFmtAnchor aAnchor( pFmt->GetAnchor() );
177 if( !aAnchor.GetCntntAnchor() ||
178 !aAnchor.GetCntntAnchor()->nNode.GetNode().GetNodes().IsDocNodes() ||
179 &aAnchor.GetCntntAnchor()->nNode.GetNode() != (SwNode*)pNode )
180 aPos.nNode = *pNode;
181 else
182 aPos.nNode = aAnchor.GetCntntAnchor()->nNode;
184 aAnchor.SetType( FLY_IN_CNTNT ); // defaulten !!
185 aAnchor.SetAnchor( &aPos );
187 // beim Ankerwechsel werden immer alle FlyFrms vom Attribut geloescht
188 // JP 25.04.95: wird innerhalb des SplitNodes die Frames verschoben
189 // koennen die Frames erhalten bleiben.
190 if( ( !pNode->GetpSwpHints() || !pNode->GetpSwpHints()->IsInSplitNode() )
191 && RES_DRAWFRMFMT != pFmt->Which() )
192 pFmt->DelFrms();
194 // stehen wir noch im falschen Dokument ?
195 if( pDoc != pFmt->GetDoc() )
197 // fuers kopieren vom Attribut das Undo immer abschalten
198 BOOL bUndo = pDoc->DoesUndo();
199 pDoc->DoUndo( FALSE );
200 SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
201 pDoc->DoUndo( bUndo );
203 bUndo = pFmt->GetDoc()->DoesUndo();
204 pFmt->GetDoc()->DoUndo( FALSE );
205 pFmt->GetDoc()->DelLayoutFmt( pFmt );
206 pFmt->GetDoc()->DoUndo( bUndo );
207 ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
209 else if( pNode->GetpSwpHints() &&
210 pNode->GetpSwpHints()->IsInSplitNode() &&
211 RES_DRAWFRMFMT != pFmt->Which() )
213 pFmt->LockModify();
214 pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
215 pFmt->UnlockModify();
217 else
218 pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
220 // Am Node haengen u.a. abhaengige CntFrms.
221 // Fuer jeden CntFrm wird ein SwFlyInCntFrm angelegt.
224 /*************************************************************************
225 * SwTxtFlyCnt::_GetFlyFrm()
227 * _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
228 * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
229 * gefunden, so wird ein neuer FlyFrm angelegt.
230 * (siehe Kommentar ind SwTxtFlyCnt::MakeTxtHint)
231 *************************************************************************/
233 SwFlyInCntFrm *SwTxtFlyCnt::_GetFlyFrm( const SwFrm *pCurrFrm )
235 SwFrmFmt* pFrmFmt = GetFlyCnt().GetFrmFmt();
236 if( RES_DRAWFRMFMT == pFrmFmt->Which() )
238 ASSERT( !this, "SwTxtFlyCnt::_GetFlyFrm: DrawInCnt-Baustelle!" );
239 return NULL;
242 SwClientIter aIter( *GetFlyCnt().pFmt );
243 ASSERT( pCurrFrm->IsTxtFrm(), "SwTxtFlyCnt::_GetFlyFrm for TxtFrms only." );
245 if( aIter.GoStart() )
247 SwTxtFrm *pFirst = (SwTxtFrm*)pCurrFrm;
248 while ( pFirst->IsFollow() )
249 pFirst = pFirst->FindMaster();
251 { SwFrm * pFrm = PTR_CAST( SwFrm, aIter() );
252 if ( pFrm )
254 SwTxtFrm *pTmp = pFirst;
256 { if( ( (SwFlyFrm*)pFrm )->GetAnchorFrm() == (SwFrm*) pTmp )
258 if ( pTmp != pCurrFrm )
260 pTmp->RemoveFly( (SwFlyFrm*)pFrm );
261 ((SwTxtFrm*)pCurrFrm)->AppendFly( (SwFlyFrm*)pFrm );
263 return (SwFlyInCntFrm*)pFrm;
265 pTmp = pTmp->GetFollow();
266 } while ( pTmp );
268 } while( aIter++ );
271 // Wir haben keinen passenden FlyFrm gefunden, deswegen wird ein
272 // neuer angelegt.
273 // Dabei wird eine sofortige Neuformatierung von pCurrFrm angestossen.
274 // Die Rekursion wird durch den Lockmechanismus in SwTxtFrm::Format()
275 // abgewuergt.
276 SwFlyInCntFrm *pFly = new SwFlyInCntFrm( (SwFlyFrmFmt*)pFrmFmt, (SwFrm*)pCurrFrm );
277 ((SwFrm*)pCurrFrm)->AppendFly( pFly );
278 pFly->RegistFlys();
280 // 7922: Wir muessen dafuer sorgen, dass der Inhalt des FlyInCnt
281 // nach seiner Konstruktion stramm durchformatiert wird.
282 // --> OD 2004-11-09 #i26945# - Use new object formatter to format Writer
283 // fly frame and its content.
284 SwObjectFormatter::FormatObj( *pFly, const_cast<SwFrm*>(pCurrFrm),
285 pCurrFrm->FindPageFrm() );
286 // <--
288 return pFly;