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 "cntfrm.hxx" // _GetFly
32 : : #include "doc.hxx"
33 : : #include <IDocumentUndoRedo.hxx>
34 : : #include "pam.hxx" // fuer SwTxtFlyCnt
35 : : #include "flyfrm.hxx" // fuer SwTxtFlyCnt
36 : : #include "ndtxt.hxx" // SwFlyFrmFmt
37 : : #include "frmfmt.hxx" // SwFlyFrmFmt
38 : : #include <fmtflcnt.hxx>
39 : : #include <txtflcnt.hxx>
40 : : #include <fmtanchr.hxx>
41 : : #include "swfont.hxx"
42 : : #include "txtfrm.hxx"
43 : : #include "flyfrms.hxx"
44 : : #include <objectformatter.hxx>
45 : : #include <switerator.hxx>
46 : :
47 : 2010 : SwFmtFlyCnt::SwFmtFlyCnt( SwFrmFmt *pFrmFmt )
48 : : : SfxPoolItem( RES_TXTATR_FLYCNT ),
49 : : pTxtAttr( 0 ),
50 : 2010 : pFmt( pFrmFmt )
51 : : {
52 : 2010 : }
53 : :
54 : 0 : int SwFmtFlyCnt::operator==( const SfxPoolItem& rAttr ) const
55 : : {
56 : : OSL_ENSURE( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
57 : : return( pTxtAttr && ((SwFmtFlyCnt&)rAttr).pTxtAttr &&
58 : 0 : *pTxtAttr->GetStart() == *((SwFmtFlyCnt&)rAttr).pTxtAttr->GetStart() &&
59 [ # # ]: 0 : pFmt == ((SwFmtFlyCnt&)rAttr).GetFrmFmt() );
[ # # # # ]
[ # # ]
60 : : }
61 : :
62 : 970 : SfxPoolItem* SwFmtFlyCnt::Clone( SfxItemPool* ) const
63 : : {
64 [ + - ]: 970 : return new SwFmtFlyCnt( pFmt );
65 : : }
66 : :
67 : 970 : SwTxtFlyCnt::SwTxtFlyCnt( SwFmtFlyCnt& rAttr, xub_StrLen nStartPos )
68 : 970 : : SwTxtAttr( rAttr, nStartPos )
69 : : {
70 : 970 : rAttr.pTxtAttr = this;
71 : 970 : SetHasDummyChar(true);
72 : 970 : }
73 : :
74 : :
75 : :
76 : : /*************************************************************************
77 : : * SwTxtFlyCnt::MakeTxtHint()
78 : : *
79 : : * An dieser Stelle soll einmal der Gesamtzusammenhang bei der Erzeugung
80 : : * eines neuen SwTxtFlyCnt erlaeutert werden.
81 : : * Das MakeTxtHint() wird z.B. im SwTxtNode::Copy() gerufen.
82 : : * Fuer die komplette Verdopplung sind folgende Schritte notwendig:
83 : : * 1) Duplizieren des pFmt incl. Inhalt, Attributen etc.
84 : : * 2) Setzen des Ankers
85 : : * 3) Benachrichtigung
86 : : * Da fuer die Bewaeltigung der Aufgaben nicht immer alle Informationen
87 : : * bereitstehen und darueber hinaus bestimmte Methoden erst zu einem
88 : : * spaeteren Zeitpunkt gerufen werden duerfen (weil nocht nicht alle
89 : : * Nodeinformationen vorliegen), verteilt sich der Ablauf.
90 : : * ad 1) MakeTxtHint() wird durch den Aufruf von SwDoc::CopyLayout()
91 : : * der das neue FlyFrmFmt erzeugt und mit dem duplizierten Inhalt des
92 : : * FlyFrm verbunden.
93 : : * ad 2) SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
94 : : * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
95 : : * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
96 : : * werden, da der Zielnode unbestimmt ist.
97 : : * ad 3) _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
98 : : * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
99 : : * gefunden, so wird ein neuer FlyFrm angelegt.
100 : : * Kritisch an diesem Vorgehen ist, dass das pCntnt->AppendFly() eine
101 : : * sofortige Neuformatierung von pCntnt anstoesst. Die Rekursion kommt
102 : : * allerdings durch den Lockmechanismus in SwTxtFrm::Format() nicht
103 : : * zu stande.
104 : : * Attraktiv ist der Umstand, dass niemand ueber die vom Node abhaengigen
105 : : * CntntFrms iterieren braucht, um die FlyInCntFrm anzulegen. Dies geschieht
106 : : * bei der Arbeit.
107 : : *************************************************************************/
108 : :
109 : 3 : void SwTxtFlyCnt::CopyFlyFmt( SwDoc* pDoc )
110 : : {
111 : 3 : SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
112 : : OSL_ENSURE( pFmt, "von welchem Format soll ich eine Kopie erzeugen?" );
113 : : // Das FlyFrmFmt muss dupliziert werden.
114 : : // In CopyLayoutFmt (siehe doclay.cxx) wird das FlyFrmFmt erzeugt
115 : : // und der Inhalt dupliziert.
116 : :
117 : : // disable undo while copying attribute
118 [ + - ][ + - ]: 3 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
119 [ + - ][ + - ]: 3 : SwFmtAnchor aAnchor( pFmt->GetAnchor() );
120 [ + - - + ]: 6 : if ((FLY_AT_PAGE != aAnchor.GetAnchorId()) &&
[ - + ]
121 : 3 : (pDoc != pFmt->GetDoc())) // different documents?
122 : : {
123 : : // JP 03.06.96: dann sorge dafuer, das der koperierte Anker auf
124 : : // gueltigen Content zeigt! Die Umsetzung auf die
125 : : // richtige Position erfolgt spaeter.
126 [ # # ][ # # ]: 0 : SwNodeIndex aIdx( pDoc->GetNodes().GetEndOfExtras(), +2 );
127 : 0 : SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
128 [ # # ]: 0 : if( !pCNd )
129 [ # # ][ # # ]: 0 : pCNd = pDoc->GetNodes().GoNext( &aIdx );
130 : :
131 [ # # ]: 0 : SwPosition* pPos = (SwPosition*)aAnchor.GetCntntAnchor();
132 [ # # ]: 0 : pPos->nNode = aIdx;
133 [ # # ]: 0 : if (FLY_AS_CHAR == aAnchor.GetAnchorId())
134 : : {
135 [ # # ][ # # ]: 0 : pPos->nContent.Assign( pCNd, 0 );
136 : : }
137 : : else
138 : : {
139 [ # # ]: 0 : pPos->nContent.Assign( 0, 0 );
140 : : OSL_ENSURE( !this, "CopyFlyFmt: Was fuer ein Anker?" );
141 [ # # ]: 0 : }
142 : : }
143 : :
144 [ + - ]: 3 : SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
145 [ + - ][ + - ]: 3 : ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
146 : 3 : }
147 : :
148 : : /*************************************************************************
149 : : * SwTxtFlyCnt::SetAnchor()
150 : : *
151 : : * SetAnchor() wird von SwTxtNode::Insert() gerufen und sorgt fuer das
152 : : * setzen des Ankers (die SwPosition des Dummy-Zeichens wird dem FlyFrmFmt
153 : : * per SetAttr bekannt gegeben). Dies kann nicht im MakeTxtHint erledigt
154 : : * werden, da der Zielnode unbestimmt ist.
155 : : * (siehe Kommentar in SwTxtFlyCnt::MakeTxtHint)
156 : : *************************************************************************/
157 : :
158 : 970 : void SwTxtFlyCnt::SetAnchor( const SwTxtNode *pNode )
159 : : {
160 : : // fuers Undo muss der neue Anker schon bekannt sein !
161 : :
162 : : // Wir ermitteln den Index im Nodesarray zum Node
163 : :
164 : 970 : SwDoc* pDoc = (SwDoc*)pNode->GetDoc();
165 : :
166 [ + - ][ + - ]: 970 : SwIndex aIdx( (SwTxtNode*)pNode, *GetStart() );
167 [ + - ][ + - ]: 970 : SwPosition aPos( *pNode->StartOfSectionNode(), aIdx );
[ + - ]
168 : 970 : SwFrmFmt* pFmt = GetFlyCnt().GetFrmFmt();
169 [ + - ][ + - ]: 970 : SwFmtAnchor aAnchor( pFmt->GetAnchor() );
170 : :
171 [ + - ][ + - ]: 2910 : if( !aAnchor.GetCntntAnchor() ||
[ + - + - ]
[ + + ][ + + ]
172 [ + - ][ + - ]: 970 : !aAnchor.GetCntntAnchor()->nNode.GetNode().GetNodes().IsDocNodes() ||
173 [ + - ]: 970 : &aAnchor.GetCntntAnchor()->nNode.GetNode() != (SwNode*)pNode )
174 [ + - ]: 3 : aPos.nNode = *pNode;
175 : : else
176 [ + - ][ + - ]: 967 : aPos.nNode = aAnchor.GetCntntAnchor()->nNode;
177 : :
178 : 970 : aAnchor.SetType( FLY_AS_CHAR ); // default!
179 [ + - ]: 970 : aAnchor.SetAnchor( &aPos );
180 : :
181 : : // beim Ankerwechsel werden immer alle FlyFrms vom Attribut geloescht
182 : : // JP 25.04.95: wird innerhalb des SplitNodes die Frames verschoben
183 : : // koennen die Frames erhalten bleiben.
184 [ + + ]: 1940 : if( ( !pNode->GetpSwpHints() || !pNode->GetpSwpHints()->IsInSplitNode() )
[ + - + + ]
[ + + ]
185 : 970 : && RES_DRAWFRMFMT != pFmt->Which() )
186 [ + - ]: 476 : pFmt->DelFrms();
187 : :
188 : : // stehen wir noch im falschen Dokument ?
189 [ - + ]: 970 : if( pDoc != pFmt->GetDoc() )
190 : : {
191 : : // disable undo while copying attribute
192 [ # # ][ # # ]: 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
193 [ # # ]: 0 : SwFrmFmt* pNew = pDoc->CopyLayoutFmt( *pFmt, aAnchor, false, false );
194 : :
195 : : ::sw::UndoGuard const undoGuardFmt(
196 [ # # ][ # # ]: 0 : pFmt->GetDoc()->GetIDocumentUndoRedo());
197 [ # # ]: 0 : pFmt->GetDoc()->DelLayoutFmt( pFmt );
198 [ # # ][ # # ]: 0 : ((SwFmtFlyCnt&)GetFlyCnt()).SetFlyFmt( pNew );
199 : : }
200 [ + + - + : 1288 : else if( pNode->GetpSwpHints() &&
# # ][ - + ]
201 : 318 : pNode->GetpSwpHints()->IsInSplitNode() &&
202 : 0 : RES_DRAWFRMFMT != pFmt->Which() )
203 : : {
204 : 0 : pFmt->LockModify();
205 [ # # ]: 0 : pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
206 : 0 : pFmt->UnlockModify();
207 : : }
208 : : else
209 [ + - ][ + - ]: 970 : pFmt->SetFmtAttr( aAnchor ); // nur den Anker neu setzen
[ + - ][ + - ]
210 : :
211 : : // Am Node haengen u.a. abhaengige CntFrms.
212 : : // Fuer jeden CntFrm wird ein SwFlyInCntFrm angelegt.
213 : 970 : }
214 : :
215 : : /*************************************************************************
216 : : * SwTxtFlyCnt::_GetFlyFrm()
217 : : *
218 : : * _GetFlyFrm() wird im Formatierungsprozess vom LineIter gerufen
219 : : * und sucht den FlyFrm zum Dummyzeichen des aktuellen CntntFrm. Wird keiner
220 : : * gefunden, so wird ein neuer FlyFrm angelegt.
221 : : * (siehe Kommentar ind SwTxtFlyCnt::MakeTxtHint)
222 : : *************************************************************************/
223 : :
224 : 562 : SwFlyInCntFrm *SwTxtFlyCnt::_GetFlyFrm( const SwFrm *pCurrFrm )
225 : : {
226 : 562 : SwFrmFmt* pFrmFmt = GetFlyCnt().GetFrmFmt();
227 [ - + ]: 562 : if( RES_DRAWFRMFMT == pFrmFmt->Which() )
228 : : {
229 : : OSL_ENSURE( !this, "SwTxtFlyCnt::_GetFlyFrm: DrawInCnt-Baustelle!" );
230 : 0 : return NULL;
231 : : }
232 : :
233 [ + - ]: 562 : SwIterator<SwFlyFrm,SwFmt> aIter( *GetFlyCnt().pFmt );
234 : : OSL_ENSURE( pCurrFrm->IsTxtFrm(), "SwTxtFlyCnt::_GetFlyFrm for TxtFrms only." );
235 [ + - ]: 562 : SwFrm* pFrm = aIter.First();
236 [ + + ]: 562 : if ( pFrm )
237 : : {
238 : 124 : SwTxtFrm *pFirst = (SwTxtFrm*)pCurrFrm;
239 [ - + ]: 124 : while ( pFirst->IsFollow() )
240 [ # # ]: 0 : pFirst = pFirst->FindMaster();
241 [ # # ]: 0 : do
242 : : {
243 : 124 : SwTxtFrm *pTmp = pFirst;
244 [ # # ]: 0 : do
245 [ + - ][ + - ]: 124 : { if( ( (SwFlyFrm*)pFrm )->GetAnchorFrm() == (SwFrm*) pTmp )
246 : : {
247 [ - + ]: 124 : if ( pTmp != pCurrFrm )
248 : : {
249 [ # # ]: 0 : pTmp->RemoveFly( (SwFlyFrm*)pFrm );
250 [ # # ]: 0 : ((SwTxtFrm*)pCurrFrm)->AppendFly( (SwFlyFrm*)pFrm );
251 : : }
252 : 124 : return (SwFlyInCntFrm*)pFrm;
253 : : }
254 : 0 : pTmp = pTmp->GetFollow();
255 : : } while ( pTmp );
256 : :
257 [ # # ]: 0 : pFrm = aIter.Next();
258 : :
259 : : } while( pFrm );
260 : : }
261 : :
262 : : // Wir haben keinen passenden FlyFrm gefunden, deswegen wird ein
263 : : // neuer angelegt.
264 : : // Dabei wird eine sofortige Neuformatierung von pCurrFrm angestossen.
265 : : // Die Rekursion wird durch den Lockmechanismus in SwTxtFrm::Format()
266 : : // abgewuergt.
267 : 438 : SwFrm* pCurrFrame = const_cast< SwFrm* >(pCurrFrm);
268 [ + - ][ + - ]: 438 : SwFlyInCntFrm *pFly = new SwFlyInCntFrm( (SwFlyFrmFmt*)pFrmFmt, pCurrFrame, pCurrFrame );
269 [ + - ]: 438 : pCurrFrame->AppendFly( pFly );
270 [ + - ]: 438 : pFly->RegistFlys();
271 : :
272 : : // 7922: Wir muessen dafuer sorgen, dass der Inhalt des FlyInCnt
273 : : // nach seiner Konstruktion stramm durchformatiert wird.
274 : : // #i26945# - Use new object formatter to format Writer
275 : : // fly frame and its content.
276 : : SwObjectFormatter::FormatObj( *pFly, const_cast<SwFrm*>(pCurrFrm),
277 [ + - ][ + - ]: 438 : pCurrFrm->FindPageFrm() );
278 : :
279 [ + - ]: 562 : return pFly;
280 : : }
281 : :
282 : :
283 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|