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