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 <switerator.hxx> 28 #include <calbck.hxx> 29 #include <node.hxx> 30 #include <ndindex.hxx> 31 #include <swtable.hxx> 32 #include <ftnfrm.hxx> 33 #include <sectfrm.hxx> 34 #include "frmfmt.hxx" 35 #include "cntfrm.hxx" 36 #include "tabfrm.hxx" 37 #include "frmtool.hxx" 38 #include "section.hxx" 39 #include "node2lay.hxx" 40 41 /* -----------------25.02.99 10:31------------------- 42 * Die SwNode2LayImpl-Klasse erledigt die eigentliche Arbeit, 43 * die SwNode2Layout-Klasse ist nur die der Oefffentlichkeit bekannte Schnittstelle 44 * --------------------------------------------------*/ 45 class SwNode2LayImpl 46 { 47 SwIterator<SwFrm,SwModify>* pIter; 48 SwModify* pMod; 49 SvPtrarr *pUpperFrms;// Zum Einsammeln der Upper 50 sal_uLong nIndex; // Der Index des einzufuegenden Nodes 51 sal_Bool bMaster : 1; // sal_True => nur Master , sal_False => nur Frames ohne Follow 52 sal_Bool bInit : 1; // Ist am SwClient bereits ein First()-Aufruf erfolgt? 53 public: 54 SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, sal_Bool bSearch ); 55 ~SwNode2LayImpl() { delete pIter; delete pUpperFrms; } 56 SwFrm* NextFrm(); // liefert den naechsten "sinnvollen" Frame 57 SwLayoutFrm* UpperFrm( SwFrm* &rpFrm, const SwNode &rNode ); 58 void SaveUpperFrms(); // Speichert (und lockt ggf.) die pUpper 59 // Fuegt unter jeden pUpper des Arrays einen Frame ein. 60 void RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd ); 61 62 SwFrm* GetFrm( const Point* pDocPos = 0, 63 const SwPosition *pPos = 0, 64 const sal_Bool bCalcFrm = sal_True ) const; 65 }; 66 67 /* -----------------25.02.99 10:38------------------- 68 * Hauptaufgabe des Ctor: Das richtige SwModify zu ermitteln, 69 * ueber das iteriert wird. 70 * Uebergibt man bSearch == sal_True, so wird der naechste Cntnt- oder TableNode 71 * gesucht, der Frames besitzt ( zum Einsammeln der pUpper ), ansonsten wird 72 * erwartet, das rNode bereits auf einem solchen Cntnt- oder TableNode sitzt, 73 * vor oder hinter den eingefuegt werden soll. 74 * --------------------------------------------------*/ 75 76 SwNode* GoNextWithFrm(const SwNodes& rNodes, SwNodeIndex *pIdx) 77 { 78 if( pIdx->GetIndex() >= rNodes.Count() - 1 ) 79 return 0; 80 81 SwNodeIndex aTmp(*pIdx, +1); 82 SwNode* pNd = 0; 83 while( aTmp < rNodes.Count()-1 ) 84 { 85 pNd = &aTmp.GetNode(); 86 bool bFound = false; 87 if ( pNd->IsCntntNode() ) 88 bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0); 89 else if ( pNd->IsTableNode() ) 90 bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 ); 91 else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() ) 92 { 93 pNd = 0; 94 break; 95 } 96 if ( bFound ) 97 break; 98 aTmp++; 99 } 100 101 if( aTmp == rNodes.Count()-1 ) 102 pNd = 0; 103 else if( pNd ) 104 (*pIdx) = aTmp; 105 return pNd; 106 } 107 108 SwNode* GoPreviousWithFrm(SwNodeIndex *pIdx) 109 { 110 if( !pIdx->GetIndex() ) 111 return 0; 112 113 SwNodeIndex aTmp( *pIdx, -1 ); 114 SwNode* pNd(0); 115 while( aTmp.GetIndex() ) 116 { 117 pNd = &aTmp.GetNode(); 118 bool bFound = false; 119 if ( pNd->IsCntntNode() ) 120 bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0); 121 else if ( pNd->IsTableNode() ) 122 bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 ); 123 else if( pNd->IsStartNode() && !pNd->IsSectionNode() ) 124 { 125 pNd = 0; 126 break; 127 } 128 if ( bFound ) 129 break; 130 aTmp--; 131 } 132 133 if( !aTmp.GetIndex() ) 134 pNd = 0; 135 else if( pNd ) 136 (*pIdx) = aTmp; 137 return pNd; 138 } 139 140 141 SwNode2LayImpl::SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, sal_Bool bSearch ) 142 : pUpperFrms( NULL ), nIndex( nIdx ), bInit( sal_False ) 143 { 144 const SwNode* pNd; 145 if( bSearch || rNode.IsSectionNode() ) 146 { 147 // Suche den naechsten Cntnt/TblNode, der einen Frame besitzt, 148 // damit wir uns vor/hinter ihn haengen koennen 149 if( !bSearch && rNode.GetIndex() < nIndex ) 150 { 151 SwNodeIndex aTmp( *rNode.EndOfSectionNode(), +1 ); 152 pNd = GoPreviousWithFrm( &aTmp ); 153 if( !bSearch && pNd && rNode.GetIndex() > pNd->GetIndex() ) 154 pNd = NULL; // Nicht ueber den Bereich hinausschiessen 155 bMaster = sal_False; 156 } 157 else 158 { 159 SwNodeIndex aTmp( rNode, -1 ); 160 pNd = GoNextWithFrm( rNode.GetNodes(), &aTmp ); 161 bMaster = sal_True; 162 if( !bSearch && pNd && rNode.EndOfSectionIndex() < pNd->GetIndex() ) 163 pNd = NULL; // Nicht ueber den Bereich hinausschiessen 164 } 165 } 166 else 167 { 168 pNd = &rNode; 169 bMaster = nIndex < rNode.GetIndex(); 170 } 171 if( pNd ) 172 { 173 if( pNd->IsCntntNode() ) 174 pMod = (SwModify*)pNd->GetCntntNode(); 175 else 176 { 177 ASSERT( pNd->IsTableNode(), "For Tablenodes only" ); 178 pMod = pNd->GetTableNode()->GetTable().GetFrmFmt(); 179 } 180 pIter = new SwIterator<SwFrm,SwModify>( *pMod ); 181 } 182 else 183 { 184 pIter = NULL; 185 pMod = 0; 186 } 187 } 188 189 /* -----------------25.02.99 10:41------------------- 190 * SwNode2LayImpl::NextFrm() liefert den naechsten "sinnvollen" Frame, 191 * beim ersten Aufruf wird am eigentlichen Iterator ein First gerufen, 192 * danach die Next-Methode. Das Ergebnis wird auf Brauchbarkeit untersucht, 193 * so werden keine Follows akzeptiert, ein Master wird beim Einsammeln der 194 * pUpper und beim Einfuegen vor ihm akzeptiert. Beim Einfuegen dahinter 195 * wird vom Master ausgehend der letzte Follow gesucht und zurueckgegeben. 196 * Wenn der Frame innerhalb eines SectionFrms liegt, wird noch festgestellt, 197 * ob statt des Frames der SectionFrm der geeignete Rueckgabewert ist, dies 198 * ist der Fall, wenn der neu einzufuegende Node ausserhalb des Bereichs liegt. 199 * --------------------------------------------------*/ 200 SwFrm* SwNode2LayImpl::NextFrm() 201 { 202 SwFrm* pRet; 203 if( !pIter ) 204 return sal_False; 205 if( !bInit ) 206 { 207 pRet = pIter->First(); 208 bInit = sal_True; 209 } 210 else 211 pRet = pIter->Next(); 212 while( pRet ) 213 { 214 SwFlowFrm* pFlow = SwFlowFrm::CastFlowFrm( pRet ); 215 ASSERT( pFlow, "Cntnt or Table expected?!" ); 216 // Follows sind fluechtige Gestalten, deshalb werden sie ignoriert. 217 // Auch wenn wir hinter dem Frame eingefuegt werden sollen, nehmen wir 218 // zunaechst den Master, hangeln uns dann aber zum letzten Follow durch. 219 if( !pFlow->IsFollow() ) 220 { 221 if( !bMaster ) 222 { 223 while( pFlow->HasFollow() ) 224 pFlow = pFlow->GetFollow(); 225 pRet = pFlow->GetFrm(); 226 } 227 if( pRet->IsInSct() ) 228 { 229 SwSectionFrm* pSct = pRet->FindSctFrm(); 230 // Vorsicht: Wenn wir in einer Fussnote sind, so kann diese 231 // Layoutmaessig in einem spaltigen Bereich liegen, obwohl 232 // sie nodemaessig ausserhalb liegt. Deshalb muss bei Fussnoten 233 // ueberprueft werden, ob auch der SectionFrm in der Fussnote 234 // und nicht ausserhalb liegt. 235 if( !pRet->IsInFtn() || pSct->IsInFtn() ) 236 { 237 ASSERT( pSct && pSct->GetSection(), "Where's my section?" ); 238 SwSectionNode* pNd = pSct->GetSection()->GetFmt()->GetSectionNode(); 239 ASSERT( pNd, "Lost SectionNode" ); 240 // Wenn der erhaltene Frame in einem Bereichsframe steht, 241 // dessen Bereich den Ausgangsnode nicht umfasst, so kehren 242 // wir mit dem SectionFrm zurueck, sonst mit dem Cntnt/TabFrm 243 if( bMaster ) 244 { 245 if( pNd->GetIndex() >= nIndex ) 246 pRet = pSct; 247 } 248 else if( pNd->EndOfSectionIndex() < nIndex ) 249 pRet = pSct; 250 } 251 } 252 return pRet; 253 } 254 pRet = pIter->Next(); 255 } 256 return NULL; 257 } 258 259 void SwNode2LayImpl::SaveUpperFrms() 260 { 261 pUpperFrms = new SvPtrarr( 0, 20 ); 262 SwFrm* pFrm; 263 while( 0 != (pFrm = NextFrm()) ) 264 { 265 SwFrm* pPrv = pFrm->GetPrev(); 266 pFrm = pFrm->GetUpper(); 267 if( pFrm ) 268 { 269 if( pFrm->IsFtnFrm() ) 270 ((SwFtnFrm*)pFrm)->ColLock(); 271 else if( pFrm->IsInSct() ) 272 pFrm->FindSctFrm()->ColLock(); 273 if( pPrv && pPrv->IsSctFrm() ) 274 ((SwSectionFrm*)pPrv)->LockJoin(); 275 pUpperFrms->Insert( (void*)pPrv, pUpperFrms->Count() ); 276 pUpperFrms->Insert( (void*)pFrm, pUpperFrms->Count() ); 277 } 278 } 279 delete pIter; 280 pIter = NULL; 281 pMod = 0; 282 } 283 284 SwLayoutFrm* SwNode2LayImpl::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode ) 285 { 286 rpFrm = NextFrm(); 287 if( !rpFrm ) 288 return NULL; 289 SwLayoutFrm* pUpper = rpFrm->GetUpper(); 290 if( rpFrm->IsSctFrm() ) 291 { 292 const SwNode* pNode = rNode.StartOfSectionNode(); 293 if( pNode->IsSectionNode() ) 294 { 295 SwFrm* pFrm = bMaster ? rpFrm->FindPrev() : rpFrm->FindNext(); 296 if( pFrm && pFrm->IsSctFrm() ) 297 { 298 // #137684#: pFrm could be a "dummy"-section 299 if( ((SwSectionFrm*)pFrm)->GetSection() && 300 (&((SwSectionNode*)pNode)->GetSection() == 301 ((SwSectionFrm*)pFrm)->GetSection()) ) 302 { 303 // OD 2004-06-02 #i22922# - consider columned sections 304 // 'Go down' the section frame as long as the layout frame 305 // is found, which would contain content. 306 while ( pFrm->IsLayoutFrm() && 307 static_cast<SwLayoutFrm*>(pFrm)->Lower() && 308 !static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsFlowFrm() && 309 static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsLayoutFrm() ) 310 { 311 pFrm = static_cast<SwLayoutFrm*>(pFrm)->Lower(); 312 } 313 ASSERT( pFrm->IsLayoutFrm(), 314 "<SwNode2LayImpl::UpperFrm(..)> - expected upper frame isn't a layout frame." ); 315 rpFrm = bMaster ? NULL 316 : static_cast<SwLayoutFrm*>(pFrm)->Lower(); 317 ASSERT( !rpFrm || rpFrm->IsFlowFrm(), 318 "<SwNode2LayImpl::UpperFrm(..)> - expected sibling isn't a flow frame." ); 319 return static_cast<SwLayoutFrm*>(pFrm); 320 } 321 322 pUpper = new SwSectionFrm(((SwSectionNode*)pNode)->GetSection(), rpFrm); 323 pUpper->Paste( rpFrm->GetUpper(), 324 bMaster ? rpFrm : rpFrm->GetNext() ); 325 static_cast<SwSectionFrm*>(pUpper)->Init(); 326 rpFrm = NULL; 327 // 'Go down' the section frame as long as the layout frame 328 // is found, which would contain content. 329 while ( pUpper->Lower() && 330 !pUpper->Lower()->IsFlowFrm() && 331 pUpper->Lower()->IsLayoutFrm() ) 332 { 333 pUpper = static_cast<SwLayoutFrm*>(pUpper->Lower()); 334 } 335 return pUpper; 336 } 337 } 338 }; 339 if( !bMaster ) 340 rpFrm = rpFrm->GetNext(); 341 return pUpper; 342 } 343 344 void SwNode2LayImpl::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd ) 345 { 346 ASSERT( pUpperFrms, "RestoreUpper without SaveUpper?" ) 347 SwNode* pNd; 348 SwDoc *pDoc = rNds.GetDoc(); 349 sal_Bool bFirst = sal_True; 350 for( ; nStt < nEnd; ++nStt ) 351 { 352 SwFrm* pNew = 0; 353 SwFrm* pNxt; 354 SwLayoutFrm* pUp; 355 if( (pNd = rNds[nStt])->IsCntntNode() ) 356 for( sal_uInt16 n = 0; n < pUpperFrms->Count(); ) 357 { 358 pNxt = (SwFrm*)(*pUpperFrms)[n++]; 359 if( bFirst && pNxt && pNxt->IsSctFrm() ) 360 ((SwSectionFrm*)pNxt)->UnlockJoin(); 361 pUp = (SwLayoutFrm*)(*pUpperFrms)[n++]; 362 if( pNxt ) 363 pNxt = pNxt->GetNext(); 364 else 365 pNxt = pUp->Lower(); 366 pNew = ((SwCntntNode*)pNd)->MakeFrm( pUp ); 367 pNew->Paste( pUp, pNxt ); 368 (*pUpperFrms)[n-2] = pNew; 369 } 370 else if( pNd->IsTableNode() ) 371 for( sal_uInt16 x = 0; x < pUpperFrms->Count(); ) 372 { 373 pNxt = (SwFrm*)(*pUpperFrms)[x++]; 374 if( bFirst && pNxt && pNxt->IsSctFrm() ) 375 ((SwSectionFrm*)pNxt)->UnlockJoin(); 376 pUp = (SwLayoutFrm*)(*pUpperFrms)[x++]; 377 if( pNxt ) 378 pNxt = pNxt->GetNext(); 379 else 380 pNxt = pUp->Lower(); 381 pNew = ((SwTableNode*)pNd)->MakeFrm( pUp ); 382 ASSERT( pNew->IsTabFrm(), "Table exspected" ); 383 pNew->Paste( pUp, pNxt ); 384 ((SwTabFrm*)pNew)->RegistFlys(); 385 (*pUpperFrms)[x-2] = pNew; 386 } 387 else if( pNd->IsSectionNode() ) 388 { 389 nStt = pNd->EndOfSectionIndex(); 390 for( sal_uInt16 x = 0; x < pUpperFrms->Count(); ) 391 { 392 pNxt = (SwFrm*)(*pUpperFrms)[x++]; 393 if( bFirst && pNxt && pNxt->IsSctFrm() ) 394 ((SwSectionFrm*)pNxt)->UnlockJoin(); 395 pUp = (SwLayoutFrm*)(*pUpperFrms)[x++]; 396 ASSERT( pUp->GetUpper() || pUp->IsFlyFrm(), "Lost Upper" ); 397 ::_InsertCnt( pUp, pDoc, pNd->GetIndex(), sal_False, nStt+1, pNxt ); 398 pNxt = pUp->GetLastLower(); 399 (*pUpperFrms)[x-2] = pNxt; 400 } 401 } 402 bFirst = sal_False; 403 } 404 for( sal_uInt16 x = 0; x < pUpperFrms->Count(); ++x ) 405 { 406 SwFrm* pTmp = (SwFrm*)(*pUpperFrms)[++x]; 407 if( pTmp->IsFtnFrm() ) 408 ((SwFtnFrm*)pTmp)->ColUnlock(); 409 else if ( pTmp->IsInSct() ) 410 { 411 SwSectionFrm* pSctFrm = pTmp->FindSctFrm(); 412 pSctFrm->ColUnlock(); 413 // OD 26.08.2003 #i18103# - invalidate size of section in order to 414 // assure, that the section is formatted, unless it was 'Collocked' 415 // from its 'collection' until its 'restoration'. 416 pSctFrm->_InvalidateSize(); 417 } 418 } 419 } 420 421 SwFrm* SwNode2LayImpl::GetFrm( const Point* pDocPos, 422 const SwPosition *pPos, 423 const sal_Bool bCalcFrm ) const 424 { 425 // mba: test if change of member pIter -> pMod broke anything 426 return pMod ? ::GetFrmOfModify( 0, *pMod, USHRT_MAX, pDocPos, pPos, bCalcFrm ) : 0; 427 } 428 429 SwNode2Layout::SwNode2Layout( const SwNode& rNd, sal_uLong nIdx ) 430 { 431 pImpl = new SwNode2LayImpl( rNd, nIdx, sal_False ); 432 } 433 434 SwNode2Layout::SwNode2Layout( const SwNode& rNd ) 435 { 436 pImpl = new SwNode2LayImpl( rNd, rNd.GetIndex(), sal_True ); 437 pImpl->SaveUpperFrms(); 438 } 439 440 void SwNode2Layout::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd ) 441 { 442 ASSERT( pImpl, "RestoreUpperFrms without SaveUpperFrms" ); 443 pImpl->RestoreUpperFrms( rNds, nStt, nEnd ); 444 } 445 446 SwFrm* SwNode2Layout::NextFrm() 447 { 448 return pImpl->NextFrm(); 449 } 450 451 SwLayoutFrm* SwNode2Layout::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode ) 452 { 453 return pImpl->UpperFrm( rpFrm, rNode ); 454 } 455 456 SwNode2Layout::~SwNode2Layout() 457 { 458 delete pImpl; 459 } 460 461 SwFrm* SwNode2Layout::GetFrm( const Point* pDocPos, 462 const SwPosition *pPos, 463 const sal_Bool bCalcFrm ) const 464 { 465 return pImpl->GetFrm( pDocPos, pPos, bCalcFrm ); 466 } 467 468 469