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 #include "pam.hxx" 27 #include "swtable.hxx" 28 #include "frame.hxx" 29 #include "rootfrm.hxx" 30 #include "pagefrm.hxx" 31 #include "flyfrm.hxx" 32 #include "viewsh.hxx" 33 #include "doc.hxx" 34 #include "viewimp.hxx" 35 #include "viewopt.hxx" 36 #include "dflyobj.hxx" 37 #include "frmtool.hxx" 38 #include "dcontact.hxx" 39 #include <editeng/brkitem.hxx> 40 #include <editeng/keepitem.hxx> 41 #include <fmtsrnd.hxx> 42 #include <fmtanchr.hxx> 43 #include <fmtpdsc.hxx> 44 #include <editeng/ulspitem.hxx> 45 #include <tgrditem.hxx> 46 #include <txtftn.hxx> 47 #include <fmtftn.hxx> 48 #include <editeng/pgrditem.hxx> 49 #include <paratr.hxx> 50 #include "ftnfrm.hxx" 51 #include "txtfrm.hxx" 52 #include "tabfrm.hxx" 53 #include "pagedesc.hxx" 54 #include "layact.hxx" 55 #include "fmtornt.hxx" 56 #include "flyfrms.hxx" 57 #include "sectfrm.hxx" 58 #include "section.hxx" 59 #include "dbg_lay.hxx" 60 #include "lineinfo.hxx" 61 #include <fmtclbl.hxx> 62 #include <sortedobjs.hxx> 63 #include <layouter.hxx> 64 #include <fmtfollowtextflow.hxx> 65 #include <switerator.hxx> 66 67 sal_Bool SwFlowFrm::bMoveBwdJump = sal_False; 68 69 70 /************************************************************************* 71 |* 72 |* SwFlowFrm::SwFlowFrm() 73 |* 74 |* Ersterstellung MA 26. Apr. 95 75 |* Letzte Aenderung MA 26. Apr. 95 76 |* 77 |*************************************************************************/ 78 79 80 SwFlowFrm::SwFlowFrm( SwFrm &rFrm ) : 81 rThis( rFrm ), 82 pFollow( 0 ) 83 { 84 bLockJoin = bIsFollow = bCntntLock = bOwnFtnNum = 85 bFtnLock = bFlyLock = sal_False; 86 } 87 88 89 /************************************************************************* 90 |* 91 |* SwFlowFrm::IsFollowLocked() 92 |* return sal_True if any follow has the JoinLocked flag 93 |* 94 |*************************************************************************/ 95 96 sal_Bool SwFlowFrm::HasLockedFollow() const 97 { 98 const SwFlowFrm* pFrm = GetFollow(); 99 while( pFrm ) 100 { 101 if( pFrm->IsJoinLocked() ) 102 return sal_True; 103 pFrm = pFrm->GetFollow(); 104 } 105 return sal_False; 106 } 107 108 /************************************************************************* 109 |* 110 |* SwFlowFrm::IsKeepFwdMoveAllowed() 111 |* 112 |* Ersterstellung MA 20. Jul. 94 113 |* Letzte Aenderung MA 16. May. 95 114 |* 115 |*************************************************************************/ 116 117 118 sal_Bool SwFlowFrm::IsKeepFwdMoveAllowed() 119 { 120 //Wenn der Vorgaenger das KeepAttribut traegt und auch dessen 121 //Vorgaenger usw. bis zum ersten der Kette und fuer diesen das 122 //IsFwdMoveAllowed ein sal_False liefert, so ist das Moven eben nicht erlaubt. 123 SwFrm *pFrm = &rThis; 124 if ( !pFrm->IsInFtn() ) 125 do 126 { if ( pFrm->GetAttrSet()->GetKeep().GetValue() ) 127 pFrm = pFrm->GetIndPrev(); 128 else 129 return sal_True; 130 } while ( pFrm ); 131 132 //Siehe IsFwdMoveAllowed() 133 sal_Bool bRet = sal_False; 134 if ( pFrm && pFrm->GetIndPrev() ) 135 bRet = sal_True; 136 return bRet; 137 } 138 139 /************************************************************************* 140 |* 141 |* SwFlowFrm::CheckKeep() 142 |* 143 |* Beschreibung 144 |* Ersterstellung MA 20. Jun. 95 145 |* Letzte Aenderung MA 09. Apr. 97 146 |* 147 |*************************************************************************/ 148 149 150 void SwFlowFrm::CheckKeep() 151 { 152 //Den 'letzten' Vorgaenger mit KeepAttribut anstossen, denn 153 //die ganze Truppe koennte zuruckrutschen. 154 SwFrm *pPre = rThis.GetIndPrev(); 155 if( pPre->IsSctFrm() ) 156 { 157 SwFrm *pLast = ((SwSectionFrm*)pPre)->FindLastCntnt(); 158 if( pLast && pLast->FindSctFrm() == pPre ) 159 pPre = pLast; 160 else 161 return; 162 } 163 SwFrm* pTmp; 164 sal_Bool bKeep; 165 while ( sal_True == (bKeep = pPre->GetAttrSet()->GetKeep().GetValue()) && 166 0 != ( pTmp = pPre->GetIndPrev() ) ) 167 { 168 if( pTmp->IsSctFrm() ) 169 { 170 SwFrm *pLast = ((SwSectionFrm*)pTmp)->FindLastCntnt(); 171 if( pLast && pLast->FindSctFrm() == pTmp ) 172 pTmp = pLast; 173 else 174 break; 175 } 176 pPre = pTmp; 177 } 178 if ( bKeep ) 179 pPre->InvalidatePos(); 180 } 181 182 /************************************************************************* 183 |* 184 |* SwFlowFrm::IsKeep() 185 |* 186 |* Ersterstellung MA 09. Apr. 97 187 |* Letzte Aenderung MA 09. Apr. 97 188 |* 189 |*************************************************************************/ 190 191 sal_Bool SwFlowFrm::IsKeep( const SwAttrSet& rAttrs, bool bCheckIfLastRowShouldKeep ) const 192 { 193 // 1. The keep attribute is ignored inside footnotes 194 // 2. For compatibility reasons, the keep attribute is 195 // ignored for frames inside table cells 196 // 3. If bBreakCheck is set to true, this function only checks 197 // if there are any break after attributes set at rAttrs 198 // or break before attributes set for the next content (or next table) 199 sal_Bool bKeep = bCheckIfLastRowShouldKeep || 200 ( !rThis.IsInFtn() && 201 ( !rThis.IsInTab() || rThis.IsTabFrm() ) && 202 rAttrs.GetKeep().GetValue() ); 203 204 ASSERT( !bCheckIfLastRowShouldKeep || rThis.IsTabFrm(), 205 "IsKeep with bCheckIfLastRowShouldKeep should only be used for tabfrms" ) 206 207 // Ignore keep attribute if there are break situations: 208 if ( bKeep ) 209 { 210 switch ( rAttrs.GetBreak().GetBreak() ) 211 { 212 case SVX_BREAK_COLUMN_AFTER: 213 case SVX_BREAK_COLUMN_BOTH: 214 case SVX_BREAK_PAGE_AFTER: 215 case SVX_BREAK_PAGE_BOTH: 216 { 217 bKeep = sal_False; 218 } 219 default: break; 220 } 221 if ( bKeep ) 222 { 223 SwFrm *pNxt; 224 if( 0 != (pNxt = rThis.FindNextCnt()) && 225 (!pFollow || pNxt != pFollow->GetFrm())) 226 { 227 // --> FME 2006-05-15 #135914# 228 // The last row of a table only keeps with the next content 229 // it they are in the same section: 230 if ( bCheckIfLastRowShouldKeep ) 231 { 232 const SwSection* pThisSection = 0; 233 const SwSection* pNextSection = 0; 234 const SwSectionFrm* pThisSectionFrm = rThis.FindSctFrm(); 235 const SwSectionFrm* pNextSectionFrm = pNxt->FindSctFrm(); 236 237 if ( pThisSectionFrm ) 238 pThisSection = pThisSectionFrm->GetSection(); 239 240 if ( pNextSectionFrm ) 241 pNextSection = pNextSectionFrm->GetSection(); 242 243 if ( pThisSection != pNextSection ) 244 bKeep = sal_False; 245 } 246 // <-- 247 248 if ( bKeep ) 249 { 250 const SwAttrSet* pSet = NULL; 251 252 if ( pNxt->IsInTab() ) 253 { 254 SwTabFrm* pTab = pNxt->FindTabFrm(); 255 if ( ! rThis.IsInTab() || rThis.FindTabFrm() != pTab ) 256 pSet = &pTab->GetFmt()->GetAttrSet(); 257 } 258 259 if ( ! pSet ) 260 pSet = pNxt->GetAttrSet(); 261 262 ASSERT( pSet, "No AttrSet to check keep attribute" ) 263 264 if ( pSet->GetPageDesc().GetPageDesc() ) 265 bKeep = sal_False; 266 else switch ( pSet->GetBreak().GetBreak() ) 267 { 268 case SVX_BREAK_COLUMN_BEFORE: 269 case SVX_BREAK_COLUMN_BOTH: 270 case SVX_BREAK_PAGE_BEFORE: 271 case SVX_BREAK_PAGE_BOTH: 272 bKeep = sal_False; 273 default: break; 274 } 275 } 276 } 277 } 278 } 279 return bKeep; 280 } 281 282 /************************************************************************* 283 |* 284 |* SwFlowFrm::BwdMoveNecessary() 285 |* 286 |* Ersterstellung MA 20. Jul. 94 287 |* Letzte Aenderung MA 02. May. 96 288 |* 289 |*************************************************************************/ 290 291 292 sal_uInt8 SwFlowFrm::BwdMoveNecessary( const SwPageFrm *pPage, const SwRect &rRect ) 293 { 294 // Der return-Wert entscheidet mit, 295 // ob auf Zurueckgeflossen werden muss, (3) 296 // ob das gute alte WouldFit gerufen werden kann (0, 1) 297 // oder ob ein Umhaengen und eine Probeformatierung sinnvoll ist (2) 298 // dabei bedeutet Bit 1, dass Objekte an mir selbst verankert sind 299 // und Bit 2, dass ich anderen Objekten ausweichen muss. 300 301 //Wenn ein SurroundObj, dass einen Umfluss wuenscht mit dem Rect ueberlappt 302 //ist der Fluss notwendig (weil die Verhaeltnisse nicht geschaetzt werden 303 //koennen), es kann allerdings ggf. eine TestFormatierung stattfinden. 304 //Wenn das SurroundObj ein Fly ist und ich selbst ein Lower bin oder der Fly 305 //Lower von mir ist, so spielt er keine Rolle. 306 //Wenn das SurroundObj in einem zeichengebunden Fly verankert ist, und ich 307 //selbst nicht Lower dieses Zeichengebundenen Flys bin, so spielt der Fly 308 //keine Rolle. 309 //#32639# Wenn das Objekt bei mir verankert ist kann ich es 310 //vernachlaessigen, weil es hoechstwahrscheinlich (!?) mitfliesst, 311 //eine TestFormatierung ist dann allerdings nicht erlaubt! 312 sal_uInt8 nRet = 0; 313 SwFlowFrm *pTmp = this; 314 do 315 { // Wenn an uns oder einem Follow Objekte haengen, so 316 // kann keine ProbeFormatierung stattfinden, da absatzgebundene 317 // nicht richtig beruecksichtigt wuerden und zeichengebundene sollten 318 // gar nicht zur Probe formatiert werden. 319 if( pTmp->GetFrm()->GetDrawObjs() ) 320 nRet = 1; 321 pTmp = pTmp->GetFollow(); 322 } while ( !nRet && pTmp ); 323 if ( pPage->GetSortedObjs() ) 324 { 325 // --> OD 2004-07-01 #i28701# - new type <SwSortedObjs> 326 const SwSortedObjs &rObjs = *pPage->GetSortedObjs(); 327 sal_uLong nIndex = ULONG_MAX; 328 for ( sal_uInt16 i = 0; nRet < 3 && i < rObjs.Count(); ++i ) 329 { 330 // --> OD 2004-07-01 #i28701# - consider changed type of 331 // <SwSortedObjs> entries. 332 SwAnchoredObject* pObj = rObjs[i]; 333 const SwFrmFmt& rFmt = pObj->GetFrmFmt(); 334 const SwRect aRect( pObj->GetObjRect() ); 335 if ( aRect.IsOver( rRect ) && 336 rFmt.GetSurround().GetSurround() != SURROUND_THROUGHT ) 337 { 338 if( rThis.IsLayoutFrm() && //Fly Lower von This? 339 Is_Lower_Of( &rThis, pObj->GetDrawObj() ) ) 340 continue; 341 if( pObj->ISA(SwFlyFrm) ) 342 { 343 const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj); 344 if ( pFly->IsAnLower( &rThis ) )//This Lower vom Fly? 345 continue; 346 } 347 348 const SwFrm* pAnchor = pObj->GetAnchorFrm(); 349 if ( pAnchor == &rThis ) 350 { 351 nRet |= 1; 352 continue; 353 } 354 355 //Nicht wenn das Objekt im Textfluss hinter mir verankert ist, 356 //denn dann weiche ich ihm nicht aus. 357 if ( ::IsFrmInSameKontext( pAnchor, &rThis ) ) 358 { 359 if ( rFmt.GetAnchor().GetAnchorId() == FLY_AT_PARA ) 360 { 361 // Den Index des anderen erhalten wir immer ueber das Ankerattr. 362 sal_uLong nTmpIndex = rFmt.GetAnchor().GetCntntAnchor()->nNode.GetIndex(); 363 // Jetzt wird noch ueberprueft, ob der aktuelle Absatz vor dem 364 // Anker des verdraengenden Objekts im Text steht, dann wird 365 // nicht ausgewichen. 366 // Der Index wird moeglichst ueber einen SwFmtAnchor ermittelt, 367 // da sonst recht teuer. 368 if( ULONG_MAX == nIndex ) 369 { 370 const SwNode *pNode; 371 if ( rThis.IsCntntFrm() ) 372 pNode = ((SwCntntFrm&)rThis).GetNode(); 373 else if( rThis.IsSctFrm() ) 374 pNode = ((SwSectionFmt*)((SwSectionFrm&)rThis). 375 GetFmt())->GetSectionNode(); 376 else 377 { 378 ASSERT( rThis.IsTabFrm(), "new FowFrm?" ); 379 pNode = ((SwTabFrm&)rThis).GetTable()-> 380 GetTabSortBoxes()[0]->GetSttNd()->FindTableNode(); 381 } 382 nIndex = pNode->GetIndex(); 383 } 384 if( nIndex < nTmpIndex ) 385 continue; 386 } 387 } 388 else 389 continue; 390 391 nRet |= 2; 392 } 393 } 394 } 395 return nRet; 396 } 397 398 /************************************************************************* 399 |* 400 |* SwFlowFrm::CutTree(), PasteTree(), MoveSubTree() 401 |* 402 |* Beschreibung Eine Spezialisierte Form des Cut() und Paste(), die 403 |* eine ganze Kette umhaengt (naehmlich this und folgende). Dabei werden 404 |* nur minimale Operationen und Benachrichtigungen ausgefuehrt. 405 |* Ersterstellung MA 18. Mar. 93 406 |* Letzte Aenderung MA 18. May. 95 407 |* 408 |*************************************************************************/ 409 410 411 SwLayoutFrm *SwFlowFrm::CutTree( SwFrm *pStart ) 412 { 413 //Der Start und alle Nachbarn werden ausgeschnitten, sie werden aneinander- 414 //gereiht und ein Henkel auf den ersten wird zurueckgeliefert. 415 //Zurueckbleibende werden geeignet invalidiert. 416 417 SwLayoutFrm *pLay = pStart->GetUpper(); 418 if ( pLay->IsInFtn() ) 419 pLay = pLay->FindFtnFrm(); 420 421 // --> OD 2006-05-08 #i58846# 422 // <pPrepare( PREP_QUOVADIS )> only for frames in footnotes 423 if( pStart->IsInFtn() ) 424 { 425 SwFrm* pTmp = pStart->GetIndPrev(); 426 if( pTmp ) 427 pTmp->Prepare( PREP_QUOVADIS ); 428 } 429 // <-- 430 431 //Nur fix auschneiden und zwar so, dass klare Verhaeltnisse bei den 432 //Verlassenen herrschen. Die Pointer der ausgeschnittenen Kette zeigen 433 //noch wer weiss wo hin. 434 if ( pStart == pStart->GetUpper()->Lower() ) 435 pStart->GetUpper()->pLower = 0; 436 if ( pStart->GetPrev() ) 437 { 438 pStart->GetPrev()->pNext = 0; 439 pStart->pPrev = 0; 440 } 441 442 if ( pLay->IsFtnFrm() ) 443 { 444 if ( !pLay->Lower() && !pLay->IsColLocked() && 445 !((SwFtnFrm*)pLay)->IsBackMoveLocked() ) 446 { 447 pLay->Cut(); 448 delete pLay; 449 } 450 else 451 { 452 sal_Bool bUnlock = !((SwFtnFrm*)pLay)->IsBackMoveLocked(); 453 ((SwFtnFrm*)pLay)->LockBackMove(); 454 pLay->InvalidateSize(); 455 pLay->Calc(); 456 SwCntntFrm *pCnt = pLay->ContainsCntnt(); 457 while ( pCnt && pLay->IsAnLower( pCnt ) ) 458 { 459 //Kann sein, dass der CntFrm gelockt ist, wir wollen hier nicht 460 //in eine endlose Seitenwanderung hineinlaufen und rufen das 461 //Calc garnicht erst! 462 ASSERT( pCnt->IsTxtFrm(), "Die Graphic ist gelandet." ); 463 if ( ((SwTxtFrm*)pCnt)->IsLocked() || 464 ((SwTxtFrm*)pCnt)->GetFollow() == pStart ) 465 break; 466 pCnt->Calc(); 467 pCnt = pCnt->GetNextCntntFrm(); 468 } 469 if( bUnlock ) 470 ((SwFtnFrm*)pLay)->UnlockBackMove(); 471 } 472 pLay = 0; 473 } 474 return pLay; 475 } 476 477 478 479 sal_Bool SwFlowFrm::PasteTree( SwFrm *pStart, SwLayoutFrm *pParent, SwFrm *pSibling, 480 SwFrm *pOldParent ) 481 { 482 //returnt sal_True wenn in der Kette ein LayoutFrm steht. 483 sal_Bool bRet = sal_False; 484 485 //Die mit pStart beginnende Kette wird vor den Sibling unter den Parent 486 //gehaengt. Fuer geeignete Invalidierung wird ebenfalls gesorgt. 487 488 //Ich bekomme eine fertige Kette. Der Anfang der Kette muss verpointert 489 //werden, dann alle Upper fuer die Kette und schliesslich dass Ende. 490 //Unterwegs werden alle geeignet invalidiert. 491 if ( pSibling ) 492 { 493 if ( 0 != (pStart->pPrev = pSibling->GetPrev()) ) 494 pStart->GetPrev()->pNext = pStart; 495 else 496 pParent->pLower = pStart; 497 pSibling->_InvalidatePos(); 498 pSibling->_InvalidatePrt(); 499 } 500 else 501 { 502 if ( 0 == (pStart->pPrev = pParent->Lower()) ) 503 pParent->pLower = pStart; 504 else 505 //Modified for #i100782#,04/03/2009 506 //If the pParent has more than 1 child nodes, former design will 507 //ignore them directly without any collection work. It will make some 508 //dangling pointers. This lead the crash... 509 //The new design will find the last child of pParent in loop way, and 510 //add the pStart after the last child. 511 // pParent->Lower()->pNext = pStart; 512 { 513 SwFrm* pTemp = pParent->pLower; 514 while (pTemp) 515 { 516 if (pTemp->pNext) 517 pTemp = pTemp->pNext; 518 else 519 { 520 pStart->pPrev = pTemp; 521 pTemp->pNext = pStart; 522 break; 523 } 524 } 525 } 526 //End modification for #i100782#,04/03/2009 527 528 // #i27145# 529 if ( pParent->IsSctFrm() ) 530 { 531 // We have no sibling because pParent is a section frame and 532 // has just been created to contain some content. The printing 533 // area of the frame behind pParent has to be invalidated, so 534 // that the correct distance between pParent and the next frame 535 // can be calculated. 536 pParent->InvalidateNextPrtArea(); 537 } 538 } 539 SwFrm *pFloat = pStart; 540 SwFrm *pLst = 0; 541 SWRECTFN( pParent ) 542 SwTwips nGrowVal = 0; 543 do 544 { pFloat->pUpper = pParent; 545 pFloat->_InvalidateAll(); 546 pFloat->CheckDirChange(); 547 548 //Ich bin Freund des TxtFrm und darf deshalb so einiges. Das mit 549 //dem CacheIdx scheint etwas riskant! 550 if ( pFloat->IsTxtFrm() ) 551 { 552 if ( ((SwTxtFrm*)pFloat)->GetCacheIdx() != USHRT_MAX ) 553 ((SwTxtFrm*)pFloat)->Init(); //Ich bin sein Freund. 554 } 555 else 556 bRet = sal_True; 557 558 nGrowVal += (pFloat->Frm().*fnRect->fnGetHeight)(); 559 if ( pFloat->GetNext() ) 560 pFloat = pFloat->GetNext(); 561 else 562 { 563 pLst = pFloat; 564 pFloat = 0; 565 } 566 } while ( pFloat ); 567 568 if ( pSibling ) 569 { 570 pLst->pNext = pSibling; 571 pSibling->pPrev = pLst; 572 if( pSibling->IsInFtn() ) 573 { 574 if( pSibling->IsSctFrm() ) 575 pSibling = ((SwSectionFrm*)pSibling)->ContainsAny(); 576 if( pSibling ) 577 pSibling->Prepare( PREP_ERGOSUM ); 578 } 579 } 580 if ( nGrowVal ) 581 { 582 if ( pOldParent && pOldParent->IsBodyFrm() ) //Fuer variable Seitenhoehe beim Browsen 583 pOldParent->Shrink( nGrowVal ); 584 pParent->Grow( nGrowVal ); 585 } 586 587 if ( pParent->IsFtnFrm() ) 588 ((SwFtnFrm*)pParent)->InvalidateNxtFtnCnts( pParent->FindPageFrm() ); 589 return bRet; 590 } 591 592 593 594 void SwFlowFrm::MoveSubTree( SwLayoutFrm* pParent, SwFrm* pSibling ) 595 { 596 ASSERT( pParent, "Kein Parent uebergeben." ); 597 ASSERT( rThis.GetUpper(), "Wo kommen wir denn her?" ); 598 599 //Sparsamer benachrichtigen wenn eine Action laeuft. 600 ViewShell *pSh = rThis.getRootFrm()->GetCurrShell(); 601 const SwViewImp *pImp = pSh ? pSh->Imp() : 0; 602 const sal_Bool bComplete = pImp && pImp->IsAction() && pImp->GetLayAction().IsComplete(); 603 604 if ( !bComplete ) 605 { 606 SwFrm *pPre = rThis.GetIndPrev(); 607 if ( pPre ) 608 { 609 pPre->SetRetouche(); 610 // --> OD 2004-11-23 #115759# - follow-up of #i26250# 611 // invalidate printing area of previous frame, if it's in a table 612 if ( pPre->GetUpper()->IsInTab() ) 613 { 614 pPre->_InvalidatePrt(); 615 } 616 // <-- 617 pPre->InvalidatePage(); 618 } 619 else 620 { rThis.GetUpper()->SetCompletePaint(); 621 rThis.GetUpper()->InvalidatePage(); 622 } 623 } 624 625 SwPageFrm *pOldPage = rThis.FindPageFrm(); 626 627 SwLayoutFrm *pOldParent = CutTree( &rThis ); 628 const sal_Bool bInvaLay = PasteTree( &rThis, pParent, pSibling, pOldParent ); 629 630 // Wenn durch das Cut&Paste ein leerer SectionFrm entstanden ist, sollte 631 // dieser automatisch verschwinden. 632 SwSectionFrm *pSct; 633 // --> OD 2006-01-04 #126020# - adjust check for empty section 634 // --> OD 2006-02-01 #130797# - correct fix #126020# 635 if ( pOldParent && !pOldParent->Lower() && 636 ( pOldParent->IsInSct() && 637 !(pSct = pOldParent->FindSctFrm())->ContainsCntnt() && 638 !pSct->ContainsAny( true ) ) ) 639 // <-- 640 { 641 pSct->DelEmpty( sal_False ); 642 } 643 644 // In einem spaltigen Bereich rufen wir lieber kein Calc "von unten" 645 if( !rThis.IsInSct() && 646 ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) ) 647 rThis.GetUpper()->Calc(); 648 else if( rThis.GetUpper()->IsSctFrm() ) 649 { 650 SwSectionFrm* pTmpSct = (SwSectionFrm*)rThis.GetUpper(); 651 sal_Bool bOld = pTmpSct->IsCntntLocked(); 652 pTmpSct->SetCntntLock( sal_True ); 653 pTmpSct->Calc(); 654 if( !bOld ) 655 pTmpSct->SetCntntLock( sal_False ); 656 } 657 SwPageFrm *pPage = rThis.FindPageFrm(); 658 659 if ( pOldPage != pPage ) 660 { 661 rThis.InvalidatePage( pPage ); 662 if ( rThis.IsLayoutFrm() ) 663 { 664 SwCntntFrm *pCnt = ((SwLayoutFrm*)&rThis)->ContainsCntnt(); 665 if ( pCnt ) 666 pCnt->InvalidatePage( pPage ); 667 } 668 else if ( pSh && pSh->GetDoc()->GetLineNumberInfo().IsRestartEachPage() 669 && pPage->FindFirstBodyCntnt() == &rThis ) 670 { 671 rThis._InvalidateLineNum(); 672 } 673 } 674 if ( bInvaLay || (pSibling && pSibling->IsLayoutFrm()) ) 675 rThis.GetUpper()->InvalidatePage( pPage ); 676 } 677 678 /************************************************************************* 679 |* 680 |* SwFlowFrm::IsAnFollow() 681 |* 682 |* Ersterstellung MA 26. Apr. 95 683 |* Letzte Aenderung MA 26. Apr. 95 684 |* 685 |*************************************************************************/ 686 687 688 sal_Bool SwFlowFrm::IsAnFollow( const SwFlowFrm *pAssumed ) const 689 { 690 const SwFlowFrm *pFoll = this; 691 do 692 { if ( pAssumed == pFoll ) 693 return sal_True; 694 pFoll = pFoll->GetFollow(); 695 } while ( pFoll ); 696 return sal_False; 697 } 698 699 700 /************************************************************************* 701 |* 702 |* SwFlowFrm::FindMaster() 703 |* 704 |* Ersterstellung MA 26. Apr. 95 705 |* Letzte Aenderung MA 26. Apr. 95 706 |* 707 |*************************************************************************/ 708 709 SwTxtFrm* SwCntntFrm::FindMaster() const 710 { 711 ASSERT( IsFollow(), "SwCntntFrm::FindMaster(): !IsFollow" ); 712 713 const SwCntntFrm* pCnt = GetPrevCntntFrm(); 714 715 while ( pCnt ) 716 { 717 if ( pCnt->HasFollow() && pCnt->GetFollow() == this ) 718 { 719 ASSERT( pCnt->IsTxtFrm(), "NoTxtFrm with follow found" ) 720 return (SwTxtFrm*)pCnt; 721 } 722 pCnt = pCnt->GetPrevCntntFrm(); 723 } 724 725 ASSERT( sal_False, "Follow ist lost in Space." ); 726 return 0; 727 } 728 729 SwSectionFrm* SwSectionFrm::FindMaster() const 730 { 731 ASSERT( IsFollow(), "SwSectionFrm::FindMaster(): !IsFollow" ); 732 733 SwIterator<SwSectionFrm,SwFmt> aIter( *pSection->GetFmt() ); 734 SwSectionFrm* pSect = aIter.First(); 735 while ( pSect ) 736 { 737 if( pSect->GetFollow() == this ) 738 return pSect; 739 pSect = aIter.Next(); 740 } 741 742 ASSERT( sal_False, "Follow ist lost in Space." ); 743 return 0; 744 } 745 746 SwTabFrm* SwTabFrm::FindMaster( bool bFirstMaster ) const 747 { 748 ASSERT( IsFollow(), "SwTabFrm::FindMaster(): !IsFollow" ); 749 750 SwIterator<SwTabFrm,SwFmt> aIter( *GetTable()->GetFrmFmt() ); 751 SwTabFrm* pTab = aIter.First(); 752 while ( pTab ) 753 { 754 if ( bFirstMaster ) 755 { 756 // 757 // Optimization. This makes code like this obsolete: 758 // while ( pTab->IsFollow() ) 759 // pTab = pTab->FindMaster(); 760 // 761 if ( !pTab->IsFollow() ) 762 { 763 SwTabFrm* pNxt = pTab; 764 while ( pNxt ) 765 { 766 if ( pNxt->GetFollow() == this ) 767 return pTab; 768 pNxt = pNxt->GetFollow(); 769 } 770 } 771 } 772 else 773 { 774 if ( pTab->GetFollow() == this ) 775 return pTab; 776 } 777 778 pTab = aIter.Next(); 779 } 780 781 ASSERT( sal_False, "Follow ist lost in Space." ); 782 return 0; 783 } 784 785 /************************************************************************* 786 |* 787 |* SwFrm::GetLeaf() 788 |* 789 |* Beschreibung Liefert das naechste/vorhergehende LayoutBlatt, 790 |* das _nicht_ unterhalb von this liegt (oder gar this selbst ist). 791 |* Ausserdem muss dieses LayoutBlatt im gleichen Textfluss wie 792 |* pAnch Ausgangsfrm liegen (Body, Ftn) 793 |* Ersterstellung MA 25. Nov. 92 794 |* Letzte Aenderung MA 25. Apr. 95 795 |* 796 |*************************************************************************/ 797 798 799 const SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd, 800 const SwFrm *pAnch ) const 801 { 802 //Ohne Fluss kein genuss... 803 if ( !(IsInDocBody() || IsInFtn() || IsInFly()) ) 804 return 0; 805 806 const SwFrm *pLeaf = this; 807 sal_Bool bFound = sal_False; 808 809 do 810 { pLeaf = ((SwFrm*)pLeaf)->GetLeaf( eMakePage, bFwd ); 811 812 if ( pLeaf && 813 (!IsLayoutFrm() || !((SwLayoutFrm*)this)->IsAnLower( pLeaf ))) 814 { 815 if ( pAnch->IsInDocBody() == pLeaf->IsInDocBody() && 816 pAnch->IsInFtn() == pLeaf->IsInFtn() ) 817 { 818 bFound = sal_True; 819 } 820 } 821 } while ( !bFound && pLeaf ); 822 823 return (const SwLayoutFrm*)pLeaf; 824 } 825 826 /************************************************************************* 827 |* 828 |* SwFrm::GetLeaf() 829 |* 830 |* Beschreibung Ruft Get[Next|Prev]Leaf 831 |* 832 |* Ersterstellung MA 20. Mar. 93 833 |* Letzte Aenderung MA 25. Apr. 95 834 |* 835 |*************************************************************************/ 836 837 838 SwLayoutFrm *SwFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd ) 839 { 840 if ( IsInFtn() ) 841 return bFwd ? GetNextFtnLeaf( eMakePage ) : GetPrevFtnLeaf( eMakePage ); 842 843 // --> OD 2005-08-16 #i53323# 844 // A frame could be inside a table AND inside a section. 845 // Thus, it has to be determined, which is the first parent. 846 bool bInTab( IsInTab() ); 847 bool bInSct( IsInSct() ); 848 if ( bInTab && bInSct ) 849 { 850 const SwFrm* pUpperFrm( GetUpper() ); 851 while ( pUpperFrm ) 852 { 853 if ( pUpperFrm->IsTabFrm() ) 854 { 855 // the table is the first. 856 bInSct = false; 857 break; 858 } 859 else if ( pUpperFrm->IsSctFrm() ) 860 { 861 // the section is the first. 862 bInTab = false; 863 break; 864 } 865 866 pUpperFrm = pUpperFrm->GetUpper(); 867 } 868 } 869 870 if ( bInTab && ( !IsTabFrm() || GetUpper()->IsCellFrm() ) ) // TABLE IN TABLE 871 return bFwd ? GetNextCellLeaf( eMakePage ) : GetPrevCellLeaf( eMakePage ); 872 873 if ( bInSct ) 874 return bFwd ? GetNextSctLeaf( eMakePage ) : GetPrevSctLeaf( eMakePage ); 875 // <-- 876 877 return bFwd ? GetNextLeaf( eMakePage ) : GetPrevLeaf( eMakePage ); 878 } 879 880 881 882 sal_Bool SwFrm::WrongPageDesc( SwPageFrm* pNew ) 883 { 884 //Jetzt wirds leider etwas kompliziert: 885 //Ich bringe ich evtl. selbst 886 //einen Pagedesc mit; der der Folgeseite muss dann damit 887 //uebereinstimmen. 888 //Anderfalls muss ich mir etwas genauer ansehen wo der 889 //Folgepagedesc herkam. 890 //Wenn die Folgeseite selbst schon sagt, dass ihr 891 //Pagedesc nicht stimmt so kann ich das Teil bedenkenlos 892 //auswechseln. 893 //Wenn die Seite meint, dass ihr Pagedesc stimmt, so heisst 894 //das leider noch immer nicht, dass ich damit etwas anfangen 895 //kann: Wenn der erste BodyCntnt einen PageDesc oder einen 896 //PageBreak wuenscht, so muss ich ebenfalls eine neue 897 //Seite einfuegen; es sein denn die gewuenschte Seite ist 898 //die richtige. 899 //Wenn ich einen neue Seite eingefuegt habe, so fangen die 900 //Probleme leider erst an, denn wahrscheinlich wird die dann 901 //folgende Seite verkehrt gewesen und ausgewechselt worden 902 //sein. Das hat zur Folge, dass ich zwar eine neue (und 903 //jetzt richtige) Seite habe, die Bedingungen zum auswechseln 904 //aber leider noch immer stimmen. 905 //Ausweg: Vorlaeufiger Versuch, nur einmal eine neue Seite 906 //einsetzen (Leerseiten werden noetigenfalls bereits von 907 //InsertPage() eingefuegt. 908 const SwFmtPageDesc &rFmtDesc = GetAttrSet()->GetPageDesc(); 909 910 //Mein Pagedesc zaehlt nicht, wenn ich ein Follow bin! 911 SwPageDesc *pDesc = 0; 912 sal_uInt16 nTmp = 0; 913 SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( this ); 914 if ( !pFlow || !pFlow->IsFollow() ) 915 { 916 pDesc = (SwPageDesc*)rFmtDesc.GetPageDesc(); 917 if( pDesc ) 918 { 919 if( !pDesc->GetRightFmt() ) 920 nTmp = 2; 921 else if( !pDesc->GetLeftFmt() ) 922 nTmp = 1; 923 else if( rFmtDesc.GetNumOffset() ) 924 nTmp = rFmtDesc.GetNumOffset(); 925 } 926 } 927 928 //Bringt der Cntnt einen Pagedesc mit oder muss zaehlt die 929 //virtuelle Seitennummer des neuen Layoutleafs? 930 // Bei Follows zaehlt der PageDesc nicht 931 const sal_Bool bOdd = nTmp ? ( nTmp % 2 ? sal_True : sal_False ) 932 : pNew->OnRightPage(); 933 if ( !pDesc ) 934 pDesc = pNew->FindPageDesc(); 935 const SwFlowFrm *pNewFlow = pNew->FindFirstBodyCntnt(); 936 // Haben wir uns selbst gefunden? 937 if( pNewFlow == pFlow ) 938 pNewFlow = NULL; 939 if ( pNewFlow && pNewFlow->GetFrm()->IsInTab() ) 940 pNewFlow = pNewFlow->GetFrm()->FindTabFrm(); 941 const SwPageDesc *pNewDesc= ( pNewFlow && !pNewFlow->IsFollow() ) 942 ? pNewFlow->GetFrm()->GetAttrSet()->GetPageDesc().GetPageDesc():0; 943 944 return ( pNew->GetPageDesc() != pDesc || // own desc ? 945 pNew->GetFmt() != (bOdd ? pDesc->GetRightFmt() : pDesc->GetLeftFmt()) || 946 ( pNewDesc && pNewDesc == pDesc ) ); 947 } 948 949 950 /************************************************************************* 951 |* 952 |* SwFrm::GetNextLeaf() 953 |* 954 |* Beschreibung Liefert das naechste LayoutBlatt in den das 955 |* Frame gemoved werden kann. 956 |* 957 |* Ersterstellung MA 16. Nov. 92 958 |* Letzte Aenderung MA 05. Dec. 96 959 |* 960 |*************************************************************************/ 961 962 SwLayoutFrm *SwFrm::GetNextLeaf( MakePageType eMakePage ) 963 { 964 ASSERT( !IsInFtn(), "GetNextLeaf(), don't call me for Ftn." ); 965 ASSERT( !IsInSct(), "GetNextLeaf(), don't call me for Sections." ); 966 967 const sal_Bool bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme 968 //Will ich auch im Body landen. 969 970 // Bei Flys macht es keinen Sinn, Seiten einzufuegen, wir wollen lediglich 971 // die Verkettung absuchen. 972 if( IsInFly() ) 973 eMakePage = MAKEPAGE_NONE; 974 975 //Bei Tabellen gleich den grossen Sprung wagen, ein einfaches GetNext... 976 //wuerde die erste Zellen und in der Folge alle weiteren Zellen nacheinander 977 //abklappern.... 978 SwLayoutFrm *pLayLeaf = 0; 979 if ( IsTabFrm() ) 980 { 981 SwCntntFrm* pTmp = ((SwTabFrm*)this)->FindLastCntnt(); 982 if ( pTmp ) 983 pLayLeaf = pTmp->GetUpper(); 984 } 985 if ( !pLayLeaf ) 986 pLayLeaf = GetNextLayoutLeaf(); 987 988 SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten 989 //nicht wieder vom Anfang gesucht 990 //wird. 991 sal_Bool bNewPg = sal_False; //nur einmal eine neue Seite einfuegen. 992 993 while ( sal_True ) 994 { 995 if ( pLayLeaf ) 996 { 997 //Es gibt noch einen weiteren LayoutFrm, mal sehen, 998 //ob er bereit ist mich aufzunehmen. 999 //Dazu braucht er nur von der gleichen Art wie mein Ausgangspunkt 1000 //sein (DocBody bzw. Footnote.) 1001 if ( pLayLeaf->FindPageFrm()->IsFtnPage() ) 1002 { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs. 1003 pLayLeaf = 0; 1004 continue; 1005 } 1006 if ( (bBody && !pLayLeaf->IsInDocBody()) || pLayLeaf->IsInTab() 1007 || pLayLeaf->IsInSct() ) 1008 { 1009 //Er will mich nicht; neuer Versuch, neues Glueck 1010 pOldLayLeaf = pLayLeaf; 1011 pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); 1012 continue; 1013 } 1014 //Er will mich, also ist er der gesuchte und ich bin fertig. 1015 //Bei einem Seitenwechsel kann es allerdings noch sein, dass 1016 //Der Seitentyp nicht der gewuenschte ist, in diesem Fall muessen 1017 //wir eine Seite des richtigen Typs einfuegen. 1018 1019 if( !IsFlowFrm() && ( eMakePage == MAKEPAGE_NONE || 1020 eMakePage==MAKEPAGE_APPEND || eMakePage==MAKEPAGE_NOSECTION ) ) 1021 return pLayLeaf; 1022 1023 SwPageFrm *pNew = pLayLeaf->FindPageFrm(); 1024 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 1025 // #111704# The pagedesc check does not make sense for frames in fly frames 1026 if ( pNew != FindPageFrm() && !bNewPg && !IsInFly() && 1027 // --> FME 2005-05-10 #i46683# 1028 // Do not consider page descriptions in browse mode (since 1029 // MoveBwd ignored them) 1030 !(pSh && pSh->GetViewOptions()->getBrowseMode() ) ) 1031 // <-- 1032 { 1033 if( WrongPageDesc( pNew ) ) 1034 { 1035 SwFtnContFrm *pCont = pNew->FindFtnCont(); 1036 if( pCont ) 1037 { 1038 // Falls die Referenz der ersten Fussnote dieser Seite 1039 // vor der Seite liegt, fuegen wir lieber keine neue Seite 1040 // ein (Bug #55620#) 1041 SwFtnFrm *pFtn = (SwFtnFrm*)pCont->Lower(); 1042 if( pFtn && pFtn->GetRef() ) 1043 { 1044 const sal_uInt16 nRefNum = pNew->GetPhyPageNum(); 1045 if( pFtn->GetRef()->GetPhyPageNum() < nRefNum ) 1046 break; 1047 } 1048 } 1049 //Erwischt, die folgende Seite ist verkehrt, also 1050 //muss eine neue eingefuegt werden. 1051 if ( eMakePage == MAKEPAGE_INSERT ) 1052 { 1053 bNewPg = sal_True; 1054 1055 SwPageFrm *pPg = pOldLayLeaf ? 1056 pOldLayLeaf->FindPageFrm() : 0; 1057 if ( pPg && pPg->IsEmptyPage() ) 1058 //Nicht hinter, sondern vor der EmptyPage einfuegen. 1059 pPg = (SwPageFrm*)pPg->GetPrev(); 1060 1061 if ( !pPg || pPg == pNew ) 1062 pPg = FindPageFrm(); 1063 1064 InsertPage( pPg, sal_False ); 1065 pLayLeaf = GetNextLayoutLeaf(); 1066 pOldLayLeaf = 0; 1067 continue; 1068 } 1069 else 1070 pLayLeaf = 0; 1071 } 1072 } 1073 break; 1074 } 1075 else 1076 { 1077 //Es gibt keinen passenden weiteren LayoutFrm, also muss eine 1078 //neue Seite her. 1079 if ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) 1080 { 1081 InsertPage( 1082 pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(), 1083 sal_False ); 1084 1085 //und nochmal das ganze 1086 pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf(); 1087 } 1088 else 1089 break; 1090 } 1091 } 1092 return pLayLeaf; 1093 } 1094 1095 /************************************************************************* 1096 |* 1097 |* SwFrm::GetPrevLeaf() 1098 |* 1099 |* Beschreibung Liefert das vorhergehende LayoutBlatt in das der 1100 |* Frame gemoved werden kann. 1101 |* Ersterstellung MA 16. Nov. 92 1102 |* Letzte Aenderung MA 25. Apr. 95 1103 |* 1104 |*************************************************************************/ 1105 1106 1107 SwLayoutFrm *SwFrm::GetPrevLeaf( MakePageType ) 1108 { 1109 ASSERT( !IsInFtn(), "GetPrevLeaf(), don't call me for Ftn." ); 1110 1111 const sal_Bool bBody = IsInDocBody(); //Wenn ich aus dem DocBody komme 1112 //will ich auch im Body landen. 1113 const sal_Bool bFly = IsInFly(); 1114 1115 SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf(); 1116 SwLayoutFrm *pPrevLeaf = 0; 1117 1118 while ( pLayLeaf ) 1119 { 1120 if ( pLayLeaf->IsInTab() || //In Tabellen geht's niemals hinein. 1121 pLayLeaf->IsInSct() ) //In Bereiche natuerlich auch nicht! 1122 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); 1123 else if ( bBody && pLayLeaf->IsInDocBody() ) 1124 { 1125 if ( pLayLeaf->Lower() ) 1126 break; 1127 pPrevLeaf = pLayLeaf; 1128 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); 1129 if ( pLayLeaf ) 1130 SwFlowFrm::SetMoveBwdJump( sal_True ); 1131 } 1132 else if ( bFly ) 1133 break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein. 1134 else 1135 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); 1136 } 1137 return pLayLeaf ? pLayLeaf : pPrevLeaf; 1138 } 1139 1140 /************************************************************************* 1141 |* 1142 |* SwFlowFrm::IsPrevObjMove() 1143 |* 1144 |* Ersterstellung MA 20. Feb. 96 1145 |* Letzte Aenderung MA 22. Feb. 96 1146 |* 1147 |*************************************************************************/ 1148 1149 1150 sal_Bool SwFlowFrm::IsPrevObjMove() const 1151 { 1152 //sal_True der FlowFrm soll auf einen Rahmen des Vorgaengers Ruecksicht nehmen 1153 // und fuer diesen ggf. Umbrechen. 1154 1155 //!!!!!!!!!!!Hack!!!!!!!!!!! 1156 const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell(); 1157 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 1158 return sal_False; 1159 1160 SwFrm *pPre = rThis.FindPrev(); 1161 1162 if ( pPre && pPre->GetDrawObjs() ) 1163 { 1164 ASSERT( SwFlowFrm::CastFlowFrm( pPre ), "new flowfrm?" ); 1165 if( SwFlowFrm::CastFlowFrm( pPre )->IsAnFollow( this ) ) 1166 return sal_False; 1167 SwLayoutFrm* pPreUp = pPre->GetUpper(); 1168 // Wenn der Upper ein SectionFrm oder die Spalte eines SectionFrms ist, 1169 // duerfen wir aus diesem durchaus heraushaengen, 1170 // es muss stattdessen der Upper des SectionFrms beruecksichtigt werden. 1171 if( pPreUp->IsInSct() ) 1172 { 1173 if( pPreUp->IsSctFrm() ) 1174 pPreUp = pPreUp->GetUpper(); 1175 else if( pPreUp->IsColBodyFrm() && 1176 pPreUp->GetUpper()->GetUpper()->IsSctFrm() ) 1177 pPreUp = pPreUp->GetUpper()->GetUpper()->GetUpper(); 1178 } 1179 // --> OD 2004-10-15 #i26945# - re-factoring: 1180 // use <GetVertPosOrientFrm()> to determine, if object has followed the 1181 // text flow to the next layout frame 1182 for ( sal_uInt16 i = 0; i < pPre->GetDrawObjs()->Count(); ++i ) 1183 { 1184 // --> OD 2004-07-01 #i28701# - consider changed type of 1185 // <SwSortedObjs> entries. 1186 const SwAnchoredObject* pObj = (*pPre->GetDrawObjs())[i]; 1187 // OD 2004-01-20 #110582# - do not consider hidden objects 1188 // --> OD 2004-10-15 #i26945# - do not consider object, which 1189 // doesn't follow the text flow. 1190 if ( pObj->GetFrmFmt().GetDoc()->IsVisibleLayerId( 1191 pObj->GetDrawObj()->GetLayer() ) && 1192 pObj->GetFrmFmt().GetFollowTextFlow().GetValue() ) 1193 // <-- 1194 { 1195 const SwLayoutFrm* pVertPosOrientFrm = pObj->GetVertPosOrientFrm(); 1196 if ( pVertPosOrientFrm && 1197 pPreUp != pVertPosOrientFrm && 1198 !pPreUp->IsAnLower( pVertPosOrientFrm ) ) 1199 { 1200 return sal_True; 1201 } 1202 } 1203 } 1204 // <-- 1205 } 1206 return sal_False; 1207 } 1208 1209 /************************************************************************* 1210 |* 1211 |* sal_Bool SwFlowFrm::IsPageBreak() 1212 |* 1213 |* Beschreibung Wenn vor dem Frm ein harter Seitenumbruch steht UND 1214 |* es einen Vorgaenger auf der gleichen Seite gibt, wird sal_True 1215 |* zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst. 1216 |* Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True 1217 |* zurueck, wenn ein PageBreak besteht. 1218 |* Fuer Follows wird der harte Seitenumbruch natuerlich nicht 1219 |* ausgewertet. 1220 |* Der Seitenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt 1221 |* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger auf der Seite 1222 |* gibt ist jede weitere Ueberlegung ueberfluessig. 1223 |* Ein Seitenumbruch (oder der Bedarf) liegt auch dann vor, wenn 1224 |* im FrmFmt ein PageDesc angegeben wird. 1225 |* Die Implementierung arbeitet zuaechst nur auf CntntFrms! 1226 |* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar. 1227 |* Ersterstellung MA ?? 1228 |* Letzte Aenderung MA 21. Mar. 95 1229 |* 1230 |*************************************************************************/ 1231 1232 1233 sal_Bool SwFlowFrm::IsPageBreak( sal_Bool bAct ) const 1234 { 1235 if ( !IsFollow() && rThis.IsInDocBody() && 1236 ( !rThis.IsInTab() || ( rThis.IsTabFrm() && !rThis.GetUpper()->IsInTab() ) ) ) // i66968 1237 { 1238 const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell(); 1239 if( pSh && pSh->GetViewOptions()->getBrowseMode() ) 1240 return sal_False; 1241 const SwAttrSet *pSet = rThis.GetAttrSet(); 1242 1243 //Vorgaenger ermitteln 1244 const SwFrm *pPrev = rThis.FindPrev(); 1245 while ( pPrev && ( !pPrev->IsInDocBody() || 1246 ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) ) 1247 pPrev = pPrev->FindPrev(); 1248 1249 if ( pPrev ) 1250 { 1251 ASSERT( pPrev->IsInDocBody(), "IsPageBreak: Not in DocBody?" ); 1252 if ( bAct ) 1253 { if ( rThis.FindPageFrm() == pPrev->FindPageFrm() ) 1254 return sal_False; 1255 } 1256 else 1257 { if ( rThis.FindPageFrm() != pPrev->FindPageFrm() ) 1258 return sal_False; 1259 } 1260 1261 const SvxBreak eBreak = pSet->GetBreak().GetBreak(); 1262 if ( eBreak == SVX_BREAK_PAGE_BEFORE || eBreak == SVX_BREAK_PAGE_BOTH ) 1263 return sal_True; 1264 else 1265 { 1266 const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak(); 1267 if ( ePrB == SVX_BREAK_PAGE_AFTER || 1268 ePrB == SVX_BREAK_PAGE_BOTH || 1269 pSet->GetPageDesc().GetPageDesc() ) 1270 return sal_True; 1271 } 1272 } 1273 } 1274 return sal_False; 1275 } 1276 1277 /************************************************************************* 1278 |* 1279 |* sal_Bool SwFlowFrm::IsColBreak() 1280 |* 1281 |* Beschreibung Wenn vor dem Frm ein harter Spaltenumbruch steht UND 1282 |* es einen Vorgaenger in der gleichen Spalte gibt, wird sal_True 1283 |* zurueckgeliefert (es muss ein PageBreak erzeugt werden) sal_False sonst. 1284 |* Wenn in bAct sal_True uebergeben wird, gibt die Funktion dann sal_True 1285 |* zurueck, wenn ein ColBreak besteht. 1286 |* Fuer Follows wird der harte Spaltenumbruch natuerlich nicht 1287 |* ausgewertet. 1288 |* Der Spaltenumbruch steht im eigenen FrmFmt (BEFORE) oder im FrmFmt 1289 |* des Vorgaengers (AFTER). Wenn es keinen Vorgaenger in der Spalte 1290 |* gibt ist jede weitere Ueberlegung ueberfluessig. 1291 |* Die Implementierung arbeitet zuaechst nur auf CntntFrms! 1292 |* -->Fuer LayoutFrms ist die Definition des Vorgaengers unklar. 1293 |* Ersterstellung MA 11. Jun. 93 1294 |* Letzte Aenderung MA 21. Mar. 95 1295 |* 1296 |*************************************************************************/ 1297 1298 sal_Bool SwFlowFrm::IsColBreak( sal_Bool bAct ) const 1299 { 1300 if ( !IsFollow() && (rThis.IsMoveable() || bAct) ) 1301 { 1302 const SwFrm *pCol = rThis.FindColFrm(); 1303 if ( pCol ) 1304 { 1305 //Vorgaenger ermitteln 1306 const SwFrm *pPrev = rThis.FindPrev(); 1307 while( pPrev && ( ( !pPrev->IsInDocBody() && !rThis.IsInFly() ) || 1308 ( pPrev->IsTxtFrm() && ((SwTxtFrm*)pPrev)->IsHiddenNow() ) ) ) 1309 pPrev = pPrev->FindPrev(); 1310 1311 if ( pPrev ) 1312 { 1313 if ( bAct ) 1314 { if ( pCol == pPrev->FindColFrm() ) 1315 return sal_False; 1316 } 1317 else 1318 { if ( pCol != pPrev->FindColFrm() ) 1319 return sal_False; 1320 } 1321 1322 const SvxBreak eBreak = rThis.GetAttrSet()->GetBreak().GetBreak(); 1323 if ( eBreak == SVX_BREAK_COLUMN_BEFORE || 1324 eBreak == SVX_BREAK_COLUMN_BOTH ) 1325 return sal_True; 1326 else 1327 { 1328 const SvxBreak &ePrB = pPrev->GetAttrSet()->GetBreak().GetBreak(); 1329 if ( ePrB == SVX_BREAK_COLUMN_AFTER || 1330 ePrB == SVX_BREAK_COLUMN_BOTH ) 1331 return sal_True; 1332 } 1333 } 1334 } 1335 } 1336 return sal_False; 1337 } 1338 1339 sal_Bool SwFlowFrm::HasParaSpaceAtPages( sal_Bool bSct ) const 1340 { 1341 if( rThis.IsInSct() ) 1342 { 1343 const SwFrm* pTmp = rThis.GetUpper(); 1344 while( pTmp ) 1345 { 1346 if( pTmp->IsCellFrm() || pTmp->IsFlyFrm() || 1347 pTmp->IsFooterFrm() || pTmp->IsHeaderFrm() || 1348 ( pTmp->IsFtnFrm() && !((SwFtnFrm*)pTmp)->GetMaster() ) ) 1349 return sal_True; 1350 if( pTmp->IsPageFrm() ) 1351 return ( pTmp->GetPrev() && !IsPageBreak(sal_True) ) ? sal_False : sal_True; 1352 if( pTmp->IsColumnFrm() && pTmp->GetPrev() ) 1353 return IsColBreak( sal_True ); 1354 if( pTmp->IsSctFrm() && ( !bSct || pTmp->GetPrev() ) ) 1355 return sal_False; 1356 pTmp = pTmp->GetUpper(); 1357 } 1358 ASSERT( sal_False, "HasParaSpaceAtPages: Where's my page?" ); 1359 return sal_False; 1360 } 1361 if( !rThis.IsInDocBody() || ( rThis.IsInTab() && !rThis.IsTabFrm()) || 1362 IsPageBreak( sal_True ) || ( rThis.FindColFrm() && IsColBreak( sal_True ) ) ) 1363 return sal_True; 1364 const SwFrm* pTmp = rThis.FindColFrm(); 1365 if( pTmp ) 1366 { 1367 if( pTmp->GetPrev() ) 1368 return sal_False; 1369 } 1370 else 1371 pTmp = &rThis; 1372 pTmp = pTmp->FindPageFrm(); 1373 return pTmp && !pTmp->GetPrev(); 1374 } 1375 1376 /** helper method to determine previous frame for calculation of the 1377 upper space 1378 1379 OD 2004-03-10 #i11860# 1380 1381 @author OD 1382 */ 1383 const SwFrm* SwFlowFrm::_GetPrevFrmForUpperSpaceCalc( const SwFrm* _pProposedPrevFrm ) const 1384 { 1385 const SwFrm* pPrevFrm = _pProposedPrevFrm 1386 ? _pProposedPrevFrm 1387 : rThis.GetPrev(); 1388 1389 // Skip hidden paragraphs and empty sections 1390 while ( pPrevFrm && 1391 ( ( pPrevFrm->IsTxtFrm() && 1392 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) || 1393 ( pPrevFrm->IsSctFrm() && 1394 !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) ) 1395 { 1396 pPrevFrm = pPrevFrm->GetPrev(); 1397 } 1398 1399 // Special case: no direct previous frame is found but frame is in footnote 1400 // Search for a previous frame in previous footnote, 1401 // if frame isn't in a section, which is also in the footnote 1402 if ( !pPrevFrm && rThis.IsInFtn() && 1403 ( rThis.IsSctFrm() || 1404 !rThis.IsInSct() || !rThis.FindSctFrm()->IsInFtn() ) ) 1405 { 1406 const SwFtnFrm* pPrevFtnFrm = 1407 static_cast<const SwFtnFrm*>(rThis.FindFtnFrm()->GetPrev()); 1408 if ( pPrevFtnFrm ) 1409 { 1410 pPrevFrm = pPrevFtnFrm->GetLastLower(); 1411 1412 // Skip hidden paragraphs and empty sections 1413 while ( pPrevFrm && 1414 ( ( pPrevFrm->IsTxtFrm() && 1415 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) || 1416 ( pPrevFrm->IsSctFrm() && 1417 !static_cast<const SwSectionFrm*>(pPrevFrm)->GetSection() ) ) ) 1418 { 1419 pPrevFrm = pPrevFrm->GetPrev(); 1420 } 1421 } 1422 } 1423 // Special case: found previous frame is a section 1424 // Search for the last content in the section 1425 if( pPrevFrm && pPrevFrm->IsSctFrm() ) 1426 { 1427 const SwSectionFrm* pPrevSectFrm = 1428 static_cast<const SwSectionFrm*>(pPrevFrm); 1429 pPrevFrm = pPrevSectFrm->FindLastCntnt(); 1430 // If the last content is in a table _inside_ the section, 1431 // take the table herself. 1432 // OD 2004-02-18 #106629# - correction: 1433 // Check directly, if table is inside table, instead of indirectly 1434 // by checking, if section isn't inside a table 1435 if ( pPrevFrm && pPrevFrm->IsInTab() ) 1436 { 1437 const SwTabFrm* pTableFrm = pPrevFrm->FindTabFrm(); 1438 if ( pPrevSectFrm->IsAnLower( pTableFrm ) ) 1439 { 1440 pPrevFrm = pTableFrm; 1441 } 1442 } 1443 // OD 2004-02-18 #106629# correction: skip hidden text frames 1444 while ( pPrevFrm && 1445 pPrevFrm->IsTxtFrm() && 1446 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) 1447 { 1448 pPrevFrm = pPrevFrm->GetPrev(); 1449 } 1450 } 1451 1452 return pPrevFrm; 1453 } 1454 1455 // OD 2004-03-12 #i11860# - add 3rd parameter <_bConsiderGrid> 1456 SwTwips SwFlowFrm::CalcUpperSpace( const SwBorderAttrs *pAttrs, 1457 const SwFrm* pPr, 1458 const bool _bConsiderGrid ) const 1459 { 1460 // OD 2004-03-10 #i11860# - use new method <GetPrevFrmForUpperSpaceCalc(..)> 1461 const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc( pPr ); 1462 1463 SwBorderAttrAccess *pAccess; 1464 SwFrm* pOwn; 1465 if( !pAttrs ) 1466 { 1467 if( rThis.IsSctFrm() ) 1468 { 1469 SwSectionFrm* pFoll = &((SwSectionFrm&)rThis); 1470 do 1471 pOwn = pFoll->ContainsAny(); 1472 while( !pOwn && 0 != ( pFoll = pFoll->GetFollow() ) ); 1473 if( !pOwn ) 1474 return 0; 1475 } 1476 else 1477 pOwn = &rThis; 1478 pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), pOwn ); 1479 pAttrs = pAccess->Get(); 1480 } 1481 else 1482 { 1483 pAccess = NULL; 1484 pOwn = &rThis; 1485 } 1486 SwTwips nUpper = 0; 1487 // OD 06.01.2004 #i11859# 1488 { 1489 const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess(); 1490 const bool bUseFormerLineSpacing = pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING); 1491 if( pPrevFrm ) 1492 { 1493 // OD 2004-03-10 #i11860# - use new method to determine needed spacing 1494 // values of found previous frame and use these values. 1495 SwTwips nPrevLowerSpace = 0; 1496 SwTwips nPrevLineSpacing = 0; 1497 // --> OD 2009-08-28 #i102458# 1498 bool bPrevLineSpacingPorportional = false; 1499 GetSpacingValuesOfFrm( (*pPrevFrm), 1500 nPrevLowerSpace, nPrevLineSpacing, 1501 bPrevLineSpacingPorportional ); 1502 // <-- 1503 if( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) ) 1504 { 1505 nUpper = nPrevLowerSpace + pAttrs->GetULSpace().GetUpper(); 1506 SwTwips nAdd = nPrevLineSpacing; 1507 // OD 07.01.2004 #i11859# - consideration of the line spacing 1508 // for the upper spacing of a text frame 1509 if ( bUseFormerLineSpacing ) 1510 { 1511 // former consideration 1512 if ( pOwn->IsTxtFrm() ) 1513 { 1514 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace() ); 1515 } 1516 nUpper += nAdd; 1517 } 1518 else 1519 { 1520 // new consideration: 1521 // Only the proportional line spacing of the previous 1522 // text frame is considered for the upper spacing and 1523 // the line spacing values are add up instead of 1524 // building its maximum. 1525 if ( pOwn->IsTxtFrm() ) 1526 { 1527 // --> OD 2009-08-28 #i102458# 1528 // Correction: 1529 // A proportional line spacing of the previous text frame 1530 // is added up to a own leading line spacing. 1531 // Otherwise, the maximum of the leading line spacing 1532 // of the previous text frame and the own leading line 1533 // spacing is built. 1534 if ( bPrevLineSpacingPorportional ) 1535 { 1536 nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ); 1537 } 1538 else 1539 { 1540 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) ); 1541 } 1542 // <-- 1543 } 1544 nUpper += nAdd; 1545 } 1546 } 1547 else 1548 { 1549 nUpper = Max( static_cast<long>(nPrevLowerSpace), 1550 static_cast<long>(pAttrs->GetULSpace().GetUpper()) ); 1551 // OD 07.01.2004 #i11859# - consideration of the line spacing 1552 // for the upper spacing of a text frame 1553 if ( bUseFormerLineSpacing ) 1554 { 1555 // former consideration 1556 if ( pOwn->IsTxtFrm() ) 1557 nUpper = Max( nUpper, ((SwTxtFrm*)pOwn)->GetLineSpace() ); 1558 if ( nPrevLineSpacing != 0 ) 1559 { 1560 nUpper = Max( nUpper, nPrevLineSpacing ); 1561 } 1562 } 1563 else 1564 { 1565 // new consideration: 1566 // Only the proportional line spacing of the previous 1567 // text frame is considered for the upper spacing and 1568 // the line spacing values are add up and added to 1569 // the paragraph spacing instead of building the 1570 // maximum of the line spacings and the paragraph spacing. 1571 SwTwips nAdd = nPrevLineSpacing; 1572 if ( pOwn->IsTxtFrm() ) 1573 { 1574 // --> OD 2009-08-28 #i102458# 1575 // Correction: 1576 // A proportional line spacing of the previous text frame 1577 // is added up to a own leading line spacing. 1578 // Otherwise, the maximum of the leading line spacing 1579 // of the previous text frame and the own leading line 1580 // spacing is built. 1581 if ( bPrevLineSpacingPorportional ) 1582 { 1583 nAdd += static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ); 1584 } 1585 else 1586 { 1587 nAdd = Max( nAdd, static_cast<SwTxtFrm&>(rThis).GetLineSpace( true ) ); 1588 } 1589 // <-- 1590 } 1591 nUpper += nAdd; 1592 } 1593 } 1594 } 1595 else if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES) && 1596 CastFlowFrm( pOwn )->HasParaSpaceAtPages( rThis.IsSctFrm() ) ) 1597 { 1598 nUpper = pAttrs->GetULSpace().GetUpper(); 1599 } 1600 } 1601 1602 // OD 2004-02-26 #i25029# - pass previous frame <pPrevFrm> 1603 // to method <GetTopLine(..)>, if parameter <pPr> is set. 1604 // Note: parameter <pPr> is set, if method is called from <SwTxtFrm::WouldFit(..)> 1605 nUpper += pAttrs->GetTopLine( rThis, (pPr ? pPrevFrm : 0L) ); 1606 1607 // OD 2004-03-12 #i11860# - consider value of new parameter <_bConsiderGrid> 1608 // and use new method <GetUpperSpaceAmountConsideredForPageGrid(..)> 1609 1610 //consider grid in square page mode 1611 if ( _bConsiderGrid && rThis.GetUpper()->GetFmt()->GetDoc()->IsSquaredPageMode() ) 1612 { 1613 nUpper += _GetUpperSpaceAmountConsideredForPageGrid( nUpper ); 1614 } 1615 1616 delete pAccess; 1617 return nUpper; 1618 } 1619 1620 /** method to detemine the upper space amount, which is considered for 1621 the page grid 1622 1623 OD 2004-03-12 #i11860# 1624 Precondition: Position of frame is valid. 1625 1626 @author OD 1627 */ 1628 SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPageGrid( 1629 const SwTwips _nUpperSpaceWithoutGrid ) const 1630 { 1631 SwTwips nUpperSpaceAmountConsideredForPageGrid = 0; 1632 1633 if ( rThis.IsInDocBody() && rThis.GetAttrSet()->GetParaGrid().GetValue() ) 1634 { 1635 const SwPageFrm* pPageFrm = rThis.FindPageFrm(); 1636 GETGRID( pPageFrm ) 1637 if( pGrid ) 1638 { 1639 const SwFrm* pBodyFrm = pPageFrm->FindBodyCont(); 1640 if ( pBodyFrm ) 1641 { 1642 const long nGridLineHeight = 1643 pGrid->GetBaseHeight() + pGrid->GetRubyHeight(); 1644 1645 SWRECTFN( (&rThis) ) 1646 const SwTwips nBodyPrtTop = (pBodyFrm->*fnRect->fnGetPrtTop)(); 1647 const SwTwips nProposedPrtTop = 1648 (*fnRect->fnYInc)( (rThis.Frm().*fnRect->fnGetTop)(), 1649 _nUpperSpaceWithoutGrid ); 1650 1651 const SwTwips nSpaceAbovePrtTop = 1652 (*fnRect->fnYDiff)( nProposedPrtTop, nBodyPrtTop ); 1653 const SwTwips nSpaceOfCompleteLinesAbove = 1654 nGridLineHeight * ( nSpaceAbovePrtTop / nGridLineHeight ); 1655 SwTwips nNewPrtTop = 1656 (*fnRect->fnYInc)( nBodyPrtTop, nSpaceOfCompleteLinesAbove ); 1657 if ( (*fnRect->fnYDiff)( nProposedPrtTop, nNewPrtTop ) > 0 ) 1658 { 1659 nNewPrtTop = (*fnRect->fnYInc)( nNewPrtTop, nGridLineHeight ); 1660 } 1661 1662 const SwTwips nNewUpperSpace = 1663 (*fnRect->fnYDiff)( nNewPrtTop, 1664 (rThis.Frm().*fnRect->fnGetTop)() ); 1665 1666 nUpperSpaceAmountConsideredForPageGrid = 1667 nNewUpperSpace - _nUpperSpaceWithoutGrid; 1668 1669 ASSERT( nUpperSpaceAmountConsideredForPageGrid >= 0, 1670 "<SwFlowFrm::GetUpperSpaceAmountConsideredForPageGrid(..)> - negative space considered for page grid!" ); 1671 } 1672 } 1673 } 1674 return nUpperSpaceAmountConsideredForPageGrid; 1675 } 1676 1677 /** method to determent the upper space amount, which is considered for 1678 the previous frame 1679 1680 OD 2004-03-11 #i11860# 1681 1682 @author OD 1683 */ 1684 SwTwips SwFlowFrm::_GetUpperSpaceAmountConsideredForPrevFrm() const 1685 { 1686 SwTwips nUpperSpaceAmountOfPrevFrm = 0; 1687 1688 const SwFrm* pPrevFrm = _GetPrevFrmForUpperSpaceCalc(); 1689 if ( pPrevFrm ) 1690 { 1691 SwTwips nPrevLowerSpace = 0; 1692 SwTwips nPrevLineSpacing = 0; 1693 // --> OD 2009-08-28 #i102458# 1694 bool bDummy = false; 1695 GetSpacingValuesOfFrm( (*pPrevFrm), nPrevLowerSpace, nPrevLineSpacing, bDummy ); 1696 // <-- 1697 if ( nPrevLowerSpace > 0 || nPrevLineSpacing > 0 ) 1698 { 1699 const IDocumentSettingAccess* pIDSA = rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess(); 1700 if ( pIDSA->get(IDocumentSettingAccess::PARA_SPACE_MAX) || 1701 !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) ) 1702 { 1703 nUpperSpaceAmountOfPrevFrm = nPrevLowerSpace + nPrevLineSpacing; 1704 } 1705 else 1706 { 1707 nUpperSpaceAmountOfPrevFrm = Max( nPrevLowerSpace, nPrevLineSpacing ); 1708 } 1709 } 1710 } 1711 1712 return nUpperSpaceAmountOfPrevFrm; 1713 } 1714 1715 /** method to determine the upper space amount, which is considered for 1716 the previous frame and the page grid, if option 'Use former object 1717 positioning' is OFF 1718 1719 OD 2004-03-18 #i11860# 1720 1721 @author OD 1722 */ 1723 SwTwips SwFlowFrm::GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() const 1724 { 1725 SwTwips nUpperSpaceAmountConsideredForPrevFrmAndPageGrid = 0; 1726 1727 if ( !rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) ) 1728 { 1729 nUpperSpaceAmountConsideredForPrevFrmAndPageGrid = 1730 _GetUpperSpaceAmountConsideredForPrevFrm() + 1731 _GetUpperSpaceAmountConsideredForPageGrid( CalcUpperSpace( 0L, 0L, false ) ); 1732 } 1733 1734 return nUpperSpaceAmountConsideredForPrevFrmAndPageGrid; 1735 } 1736 1737 /** calculation of lower space 1738 1739 OD 2004-03-02 #106629# 1740 1741 @author OD 1742 */ 1743 SwTwips SwFlowFrm::CalcLowerSpace( const SwBorderAttrs* _pAttrs ) const 1744 { 1745 SwTwips nLowerSpace = 0; 1746 1747 SwBorderAttrAccess* pAttrAccess = 0L; 1748 if ( !_pAttrs ) 1749 { 1750 pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), &rThis ); 1751 _pAttrs = pAttrAccess->Get(); 1752 } 1753 1754 sal_Bool bCommonBorder = sal_True; 1755 if ( rThis.IsInSct() && rThis.GetUpper()->IsColBodyFrm() ) 1756 { 1757 const SwSectionFrm* pSectFrm = rThis.FindSctFrm(); 1758 bCommonBorder = pSectFrm->GetFmt()->GetBalancedColumns().GetValue(); 1759 } 1760 nLowerSpace = bCommonBorder ? 1761 _pAttrs->GetBottomLine( rThis ) : 1762 _pAttrs->CalcBottomLine(); 1763 1764 // --> OD 2004-07-16 #i26250# 1765 // - correct consideration of table frames 1766 // - use new method <CalcAddLowerSpaceAsLastInTableCell(..)> 1767 if ( ( ( rThis.IsTabFrm() && rThis.GetUpper()->IsInTab() ) || 1768 // --> OD 2004-11-16 #115759# - no lower spacing, if frame has a follow 1769 ( rThis.IsInTab() && !GetFollow() ) ) && 1770 // <-- 1771 !rThis.GetIndNext() ) 1772 { 1773 nLowerSpace += CalcAddLowerSpaceAsLastInTableCell( _pAttrs ); 1774 } 1775 // <-- 1776 1777 delete pAttrAccess; 1778 1779 return nLowerSpace; 1780 } 1781 1782 /** calculation of the additional space to be considered, if flow frame 1783 is the last inside a table cell 1784 1785 OD 2004-07-16 #i26250# 1786 1787 @author OD 1788 */ 1789 SwTwips SwFlowFrm::CalcAddLowerSpaceAsLastInTableCell( 1790 const SwBorderAttrs* _pAttrs ) const 1791 { 1792 SwTwips nAdditionalLowerSpace = 0; 1793 1794 if ( rThis.GetUpper()->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) ) 1795 { 1796 const SwFrm* pFrm = &rThis; 1797 if ( pFrm->IsSctFrm() ) 1798 { 1799 const SwSectionFrm* pSectFrm = static_cast<const SwSectionFrm*>(pFrm); 1800 pFrm = pSectFrm->FindLastCntnt(); 1801 if ( pFrm && pFrm->IsInTab() ) 1802 { 1803 const SwTabFrm* pTableFrm = pFrm->FindTabFrm(); 1804 if ( pSectFrm->IsAnLower( pTableFrm ) ) 1805 { 1806 pFrm = pTableFrm; 1807 } 1808 } 1809 } 1810 1811 SwBorderAttrAccess* pAttrAccess = 0L; 1812 if ( !_pAttrs || pFrm != &rThis ) 1813 { 1814 pAttrAccess = new SwBorderAttrAccess( SwFrm::GetCache(), pFrm ); 1815 _pAttrs = pAttrAccess->Get(); 1816 } 1817 1818 nAdditionalLowerSpace += _pAttrs->GetULSpace().GetLower(); 1819 1820 delete pAttrAccess; 1821 } 1822 1823 return nAdditionalLowerSpace; 1824 } 1825 1826 /************************************************************************* 1827 |* 1828 |* sal_Bool SwFlowFrm::CheckMoveFwd() 1829 |* 1830 |* Beschreibung Moved den Frm vorwaerts wenn es durch die aktuellen 1831 |* Bedingungen und Attribute notwendig erscheint. 1832 |* Ersterstellung MA 05. Dec. 96 1833 |* Letzte Aenderung MA 09. Mar. 98 1834 |* 1835 |*************************************************************************/ 1836 1837 1838 sal_Bool SwFlowFrm::CheckMoveFwd( sal_Bool &rbMakePage, sal_Bool bKeep, sal_Bool ) 1839 { 1840 const SwFrm* pNxt = rThis.GetIndNext(); 1841 1842 if ( bKeep && //!bMovedBwd && 1843 ( !pNxt || ( pNxt->IsTxtFrm() && ((SwTxtFrm*)pNxt)->IsEmptyMaster() ) ) && 1844 ( 0 != (pNxt = rThis.FindNext()) ) && IsKeepFwdMoveAllowed() ) 1845 { 1846 if( pNxt->IsSctFrm() ) 1847 { // Nicht auf leere SectionFrms hereinfallen 1848 const SwFrm* pTmp = NULL; 1849 while( pNxt && pNxt->IsSctFrm() && 1850 ( !((SwSectionFrm*)pNxt)->GetSection() || 1851 0 == ( pTmp = ((SwSectionFrm*)pNxt)->ContainsAny() ) ) ) 1852 { 1853 pNxt = pNxt->FindNext(); 1854 pTmp = NULL; 1855 } 1856 if( pTmp ) 1857 pNxt = pTmp; // the content of the next notempty sectionfrm 1858 } 1859 if( pNxt && pNxt->GetValidPosFlag() ) 1860 { 1861 sal_Bool bMove = sal_False; 1862 const SwSectionFrm *pSct = rThis.FindSctFrm(); 1863 if( pSct && !pSct->GetValidSizeFlag() ) 1864 { 1865 const SwSectionFrm* pNxtSct = pNxt->FindSctFrm(); 1866 if( pNxtSct && pSct->IsAnFollow( pNxtSct ) ) 1867 bMove = sal_True; 1868 } 1869 else 1870 bMove = sal_True; 1871 if( bMove ) 1872 { 1873 //Keep together with the following frame 1874 MoveFwd( rbMakePage, sal_False ); 1875 return sal_True; 1876 } 1877 } 1878 } 1879 1880 sal_Bool bMovedFwd = sal_False; 1881 1882 if ( rThis.GetIndPrev() ) 1883 { 1884 if ( IsPrevObjMove() ) //Auf Objekte des Prev Ruecksicht nehmen? 1885 { 1886 bMovedFwd = sal_True; 1887 if ( !MoveFwd( rbMakePage, sal_False ) ) 1888 rbMakePage = sal_False; 1889 } 1890 else 1891 { 1892 if ( IsPageBreak( sal_False ) ) 1893 { 1894 while ( MoveFwd( rbMakePage, sal_True ) ) 1895 /* do nothing */; 1896 rbMakePage = sal_False; 1897 bMovedFwd = sal_True; 1898 } 1899 else if ( IsColBreak ( sal_False ) ) 1900 { 1901 const SwPageFrm *pPage = rThis.FindPageFrm(); 1902 SwFrm *pCol = rThis.FindColFrm(); 1903 do 1904 { MoveFwd( rbMakePage, sal_False ); 1905 SwFrm *pTmp = rThis.FindColFrm(); 1906 if( pTmp != pCol ) 1907 { 1908 bMovedFwd = sal_True; 1909 pCol = pTmp; 1910 } 1911 else 1912 break; 1913 } while ( IsColBreak( sal_False ) ); 1914 if ( pPage != rThis.FindPageFrm() ) 1915 rbMakePage = sal_False; 1916 } 1917 } 1918 } 1919 return bMovedFwd; 1920 } 1921 1922 /************************************************************************* 1923 |* 1924 |* sal_Bool SwFlowFrm::MoveFwd() 1925 |* 1926 |* Beschreibung Returnwert sagt, ob der Frm die Seite gewechselt hat. 1927 |* Ersterstellung MA 05. Dec. 96 1928 |* Letzte Aenderung MA 05. Dec. 96 1929 |* 1930 |*************************************************************************/ 1931 1932 1933 sal_Bool SwFlowFrm::MoveFwd( sal_Bool bMakePage, sal_Bool bPageBreak, sal_Bool bMoveAlways ) 1934 { 1935 //!!!!MoveFtnCntFwd muss ggf. mitgepflegt werden. 1936 SwFtnBossFrm *pOldBoss = rThis.FindFtnBossFrm(); 1937 if ( rThis.IsInFtn() ) 1938 return ((SwCntntFrm&)rThis).MoveFtnCntFwd( bMakePage, pOldBoss ); 1939 1940 if( !IsFwdMoveAllowed() && !bMoveAlways ) 1941 { 1942 sal_Bool bNoFwd = sal_True; 1943 if( rThis.IsInSct() ) 1944 { 1945 SwFtnBossFrm* pBoss = rThis.FindFtnBossFrm(); 1946 bNoFwd = !pBoss->IsInSct() || ( !pBoss->Lower()->GetNext() && 1947 !pBoss->GetPrev() ); 1948 } 1949 1950 // Allow the MoveFwd even if we do not have an IndPrev in these cases: 1951 if ( rThis.IsInTab() && 1952 ( !rThis.IsTabFrm() || 1953 ( rThis.GetUpper()->IsInTab() && 1954 rThis.GetUpper()->FindTabFrm()->IsFwdMoveAllowed() ) ) && 1955 0 != const_cast<SwFrm&>(rThis).GetNextCellLeaf( MAKEPAGE_NONE ) ) 1956 /* 1957 && 1958 // NEW TABLES 1959 // Have a look at our main competitor: We don't move inside row span cells: 1960 ( !rThis.GetUpper()->IsCellFrm() || !rThis.GetUpper()->IsLeaveUpperAllowed() ) )*/ 1961 { 1962 bNoFwd = sal_False; 1963 } 1964 1965 if( bNoFwd ) 1966 { 1967 //Fuer PageBreak ist das Moven erlaubt, wenn der Frm nicht 1968 //bereits der erste der Seite ist. 1969 if ( !bPageBreak ) 1970 return sal_False; 1971 1972 const SwFrm *pCol = rThis.FindColFrm(); 1973 if ( !pCol || !pCol->GetPrev() ) 1974 return sal_False; 1975 } 1976 } 1977 1978 sal_Bool bSamePage = sal_True; 1979 SwLayoutFrm *pNewUpper = 1980 rThis.GetLeaf( bMakePage ? MAKEPAGE_INSERT : MAKEPAGE_NONE, sal_True ); 1981 1982 if ( pNewUpper ) 1983 { 1984 PROTOCOL_ENTER( &rThis, PROT_MOVE_FWD, 0, 0 ); 1985 SwPageFrm *pOldPage = pOldBoss->FindPageFrm(); 1986 //Wir moven uns und alle direkten Nachfolger vor den ersten 1987 //CntntFrm unterhalb des neuen Uppers. 1988 1989 // Wenn unser NewUpper in einem SectionFrm liegt, muessen wir 1990 // verhindern, dass sich dieser im Calc selbst zerstoert 1991 SwSectionFrm* pSect = pNewUpper->FindSctFrm(); 1992 sal_Bool bUnlock = sal_False; 1993 if( pSect ) 1994 { 1995 // Wenn wir nur innerhalb unseres SectionFrms die Spalte wechseln, 1996 // rufen wir lieber kein Calc, sonst wird noch der SectionFrm 1997 // formatiert, der wiederum uns ruft etc. 1998 if( pSect != rThis.FindSctFrm() ) 1999 { 2000 bUnlock = !pSect->IsColLocked(); 2001 pSect->ColLock(); 2002 pNewUpper->Calc(); 2003 if( bUnlock ) 2004 pSect->ColUnlock(); 2005 } 2006 } 2007 // Do not calculate split cell frames. 2008 else if ( !pNewUpper->IsCellFrm() || ((SwLayoutFrm*)pNewUpper)->Lower() ) 2009 pNewUpper->Calc(); 2010 2011 SwFtnBossFrm *pNewBoss = pNewUpper->FindFtnBossFrm(); 2012 sal_Bool bBossChg = pNewBoss != pOldBoss; 2013 pNewBoss = pNewBoss->FindFtnBossFrm( sal_True ); 2014 pOldBoss = pOldBoss->FindFtnBossFrm( sal_True ); 2015 SwPageFrm* pNewPage = pOldPage; 2016 2017 // First, we move the footnotes. 2018 sal_Bool bFtnMoved = sal_False; 2019 2020 // --> FME 2004-07-15 #i26831# 2021 // If pSect has just been created, the printing area of pSect has 2022 // been calculated based on the first content of its follow. 2023 // In this case we prefer to call a SimpleFormat for this new 2024 // section after we inserted the contents. Otherwise the section 2025 // frame will invalidate its lowers, if its printing area changes 2026 // in SwSectionFrm::Format, which can cause loops. 2027 const bool bForceSimpleFormat = pSect && pSect->HasFollow() && 2028 !pSect->ContainsAny(); 2029 // <-- 2030 2031 if ( pNewBoss != pOldBoss ) 2032 { 2033 pNewPage = pNewBoss->FindPageFrm(); 2034 bSamePage = pNewPage == pOldPage; 2035 //Damit die Fussnoten nicht auf dumme Gedanken kommen 2036 //setzen wir hier die Deadline. 2037 SWRECTFN( pOldBoss ) 2038 SwSaveFtnHeight aHeight( pOldBoss, 2039 (pOldBoss->Frm().*fnRect->fnGetBottom)() ); 2040 SwCntntFrm* pStart = rThis.IsCntntFrm() ? 2041 (SwCntntFrm*)&rThis : ((SwLayoutFrm&)rThis).ContainsCntnt(); 2042 ASSERT( pStart || ( rThis.IsTabFrm() && !((SwTabFrm&)rThis).Lower() ), 2043 "MoveFwd: Missing Content" ); 2044 SwLayoutFrm* pBody = pStart ? ( pStart->IsTxtFrm() ? 2045 (SwLayoutFrm*)((SwTxtFrm*)pStart)->FindBodyFrm() : 0 ) : 0; 2046 if( pBody ) 2047 bFtnMoved = pBody->MoveLowerFtns( pStart, pOldBoss, pNewBoss, 2048 sal_False); 2049 } 2050 // Bei SectionFrms ist es moeglich, dass wir selbst durch pNewUpper->Calc() 2051 // bewegt wurden, z. B. in den pNewUpper. 2052 // MoveSubTree bzw. PasteTree ist auf so etwas nicht vorbereitet. 2053 if( pNewUpper != rThis.GetUpper() ) 2054 { 2055 // --> FME 2004-04-19 #i27145# 2056 SwSectionFrm* pOldSct = 0; 2057 if ( rThis.GetUpper()->IsSctFrm() ) 2058 { 2059 pOldSct = static_cast<SwSectionFrm*>(rThis.GetUpper()); 2060 } 2061 // <-- 2062 2063 MoveSubTree( pNewUpper, pNewUpper->Lower() ); 2064 2065 // --> FME 2004-04-19 #i27145# 2066 if ( pOldSct && pOldSct->GetSection() ) 2067 { 2068 // Prevent loops by setting the new height at 2069 // the section frame if footnotes have been moved. 2070 // Otherwise the call of SwLayNotify::~SwLayNotify() for 2071 // the (invalid) section frame will invalidate the first 2072 // lower of its follow, because it grows due to the removed 2073 // footnotes. 2074 // Note: If pOldSct has become empty during MoveSubTree, it 2075 // has already been scheduled for removal. No SimpleFormat 2076 // for these. 2077 pOldSct->SimpleFormat(); 2078 } 2079 // <-- 2080 2081 // --> FME 2004-07-15 #i26831# 2082 if ( bForceSimpleFormat ) 2083 { 2084 pSect->SimpleFormat(); 2085 } 2086 // <-- 2087 2088 if ( bFtnMoved && !bSamePage ) 2089 { 2090 pOldPage->UpdateFtnNum(); 2091 pNewPage->UpdateFtnNum(); 2092 } 2093 2094 if( bBossChg ) 2095 { 2096 rThis.Prepare( PREP_BOSS_CHGD, 0, sal_False ); 2097 if( !bSamePage ) 2098 { 2099 ViewShell *pSh = rThis.getRootFrm()->GetCurrShell(); 2100 if ( pSh && !pSh->Imp()->IsUpdateExpFlds() ) 2101 pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher erledigt! 2102 2103 pNewPage->InvalidateSpelling(); 2104 pNewPage->InvalidateSmartTags(); // SMARTTAGS 2105 pNewPage->InvalidateAutoCompleteWords(); 2106 pNewPage->InvalidateWordCount(); 2107 } 2108 } 2109 } 2110 // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout 2111 const ViewShell *pSh = rThis.getRootFrm()->GetCurrShell(); 2112 2113 if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ) 2114 { 2115 // --> OD 2009-12-31 #i106452# 2116 // check page description not only in situation with sections. 2117 if ( !bSamePage && 2118 ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() || 2119 pOldPage->GetPageDesc()->GetFollow() != pNewPage->GetPageDesc() ) ) 2120 { 2121 SwFrm::CheckPageDescs( pNewPage, sal_False ); 2122 } 2123 // <-- 2124 } 2125 } 2126 return bSamePage; 2127 } 2128 2129 2130 /************************************************************************* 2131 |* 2132 |* sal_Bool SwFlowFrm::MoveBwd() 2133 |* 2134 |* Beschreibung Returnwert sagt, ob der Frm die Seite wechseln soll. 2135 |* Sollte von abgeleiteten Klassen gerufen werden. 2136 |* Das moven selbst muessen die abgeleiteten uebernehmen. 2137 |* Ersterstellung MA 05. Dec. 96 2138 |* Letzte Aenderung MA 05. Dec. 96 2139 |* 2140 |*************************************************************************/ 2141 2142 sal_Bool SwFlowFrm::MoveBwd( sal_Bool &rbReformat ) 2143 { 2144 SwFlowFrm::SetMoveBwdJump( sal_False ); 2145 2146 SwFtnFrm* pFtn = rThis.FindFtnFrm(); 2147 if ( pFtn && pFtn->IsBackMoveLocked() ) 2148 return sal_False; 2149 2150 // --> OD 2004-11-29 #115759# - text frames, which are directly inside 2151 // tables aren't allowed to move backward. 2152 if ( rThis.IsTxtFrm() && rThis.IsInTab() ) 2153 { 2154 const SwLayoutFrm* pUpperFrm = rThis.GetUpper(); 2155 while ( pUpperFrm ) 2156 { 2157 if ( pUpperFrm->IsTabFrm() ) 2158 { 2159 return sal_False; 2160 } 2161 else if ( pUpperFrm->IsColumnFrm() && pUpperFrm->IsInSct() ) 2162 { 2163 break; 2164 } 2165 pUpperFrm = pUpperFrm->GetUpper(); 2166 } 2167 } 2168 // <-- 2169 2170 SwFtnBossFrm * pOldBoss = rThis.FindFtnBossFrm(); 2171 SwPageFrm * const pOldPage = pOldBoss->FindPageFrm(); 2172 SwLayoutFrm *pNewUpper = 0; 2173 sal_Bool bCheckPageDescs = sal_False; 2174 bool bCheckPageDescOfNextPage = false; 2175 2176 if ( pFtn ) 2177 { 2178 //Wenn die Fussnote bereits auf der gleichen Seite/Spalte wie die Referenz 2179 //steht, ist nix mit zurueckfliessen. Die breaks brauche fuer die 2180 //Fussnoten nicht geprueft zu werden. 2181 2182 // --> FME 2004-11-15 #i37084# FindLastCntnt does not necessarily 2183 // have to have a result != 0 2184 SwFrm* pRef = 0; 2185 const bool bEndnote = pFtn->GetAttr()->GetFtn().IsEndNote(); 2186 if( bEndnote && pFtn->IsInSct() ) 2187 { 2188 SwSectionFrm* pSect = pFtn->FindSctFrm(); 2189 if( pSect->IsEndnAtEnd() ) 2190 pRef = pSect->FindLastCntnt( FINDMODE_LASTCNT ); 2191 } 2192 if( !pRef ) 2193 pRef = pFtn->GetRef(); 2194 // <-- 2195 2196 ASSERT( pRef, "MoveBwd: Endnote for an empty section?" ); 2197 2198 if( !bEndnote ) 2199 pOldBoss = pOldBoss->FindFtnBossFrm( sal_True ); 2200 SwFtnBossFrm *pRefBoss = pRef->FindFtnBossFrm( !bEndnote ); 2201 if ( pOldBoss != pRefBoss && 2202 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)> 2203 ( !bEndnote || 2204 pRefBoss->IsBefore( pOldBoss ) ) 2205 ) 2206 pNewUpper = rThis.GetLeaf( MAKEPAGE_FTN, sal_False ); 2207 } 2208 else if ( IsPageBreak( sal_True ) ) //PageBreak zu beachten? 2209 { 2210 //Wenn auf der vorhergehenden Seite kein Frm im Body steht, 2211 //so ist das Zurueckfliessen trotz Pagebreak sinnvoll 2212 //(sonst: leere Seite). 2213 //Natuerlich muessen Leereseiten geflissentlich uebersehen werden! 2214 const SwFrm *pFlow = &rThis; 2215 do 2216 { 2217 pFlow = pFlow->FindPrev(); 2218 } while ( pFlow && 2219 ( pFlow->FindPageFrm() == pOldPage || 2220 !pFlow->IsInDocBody() ) ); 2221 if ( pFlow ) 2222 { 2223 long nDiff = pOldPage->GetPhyPageNum() - pFlow->GetPhyPageNum(); 2224 if ( nDiff > 1 ) 2225 { 2226 if ( ((SwPageFrm*)pOldPage->GetPrev())->IsEmptyPage() ) 2227 nDiff -= 1; 2228 if ( nDiff > 1 ) 2229 { 2230 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False ); 2231 // --> OD 2006-05-08 #i53139# 2232 // Now <pNewUpper> is a previous layout frame, which contains 2233 // content. But the new upper layout frame has to be the next one. 2234 // Thus, hack for issue i14206 no longer needed, but fix for issue 114442 2235 // --> OD 2006-05-17 #136024# - correct fix for i53139: 2236 // Check for wrong page description before using next new upper. 2237 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139 2238 // Check for correct type of new next upper layout frame 2239 // --> OD 2006-06-08 #136538# - another correction of fix for i53139 2240 // Assumption, that in all cases <pNewUpper> is a previous 2241 // layout frame, which contains content, is wrong. 2242 // --> OD 2006-07-05 #136538# - another correction of fix for i53139 2243 // Beside type check, check also, if proposed new next upper 2244 // frame is inside the same frame types. 2245 // --> OD 2007-01-10 #i73194# - and yet another correction 2246 // of fix for i53139: 2247 // Assure that the new next upper layout frame doesn't 2248 // equal the current one. 2249 // E.g.: content is on page 3, on page 2 is only a 'ghost' 2250 // section and on page 1 is normal content. Method <FindPrev(..)> 2251 // will find the last content of page 1, but <GetLeaf(..)> 2252 // returns new upper on page 2. 2253 if ( pNewUpper->Lower() ) 2254 { 2255 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True ); 2256 if ( pNewNextUpper && 2257 pNewNextUpper != rThis.GetUpper() && 2258 pNewNextUpper->GetType() == pNewUpper->GetType() && 2259 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() && 2260 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() && 2261 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() && 2262 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() && 2263 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) ) 2264 { 2265 pNewUpper = pNewNextUpper; 2266 bCheckPageDescOfNextPage = true; 2267 } 2268 } 2269 // <-- 2270 2271 bCheckPageDescs = sal_True; 2272 } 2273 } 2274 } 2275 } 2276 else if ( IsColBreak( sal_True ) ) 2277 { 2278 //Wenn in der vorhergehenden Spalte kein CntntFrm steht, so ist 2279 //das Zurueckfliessen trotz ColumnBreak sinnvoll 2280 //(sonst: leere Spalte). 2281 if( rThis.IsInSct() ) 2282 { 2283 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False ); 2284 if( pNewUpper && !SwFlowFrm::IsMoveBwdJump() && 2285 ( pNewUpper->ContainsCntnt() || 2286 ( ( !pNewUpper->IsColBodyFrm() || 2287 !pNewUpper->GetUpper()->GetPrev() ) && 2288 !pNewUpper->FindSctFrm()->GetPrev() ) ) ) 2289 { 2290 pNewUpper = 0; 2291 } 2292 // --> OD 2006-05-08 #i53139# 2293 // --> OD 2006-09-11 #i69409# - check <pNewUpper> 2294 // --> OD 2006-11-02 #i71065# - check <SwFlowFrm::IsMoveBwdJump()> 2295 else if ( pNewUpper && !SwFlowFrm::IsMoveBwdJump() ) 2296 // <-- 2297 { 2298 // Now <pNewUpper> is a previous layout frame, which 2299 // contains content. But the new upper layout frame 2300 // has to be the next one. 2301 // --> OD 2006-05-17 #136024# - correct fix for i53139 2302 // Check for wrong page description before using next new upper. 2303 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139 2304 // Check for correct type of new next upper layout frame 2305 // --> OD 2006-07-05 #136538# - another correction of fix for i53139 2306 // Beside type check, check also, if proposed new next upper 2307 // frame is inside the same frame types. 2308 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NOSECTION, sal_True ); 2309 if ( pNewNextUpper && 2310 pNewNextUpper->GetType() == pNewUpper->GetType() && 2311 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() && 2312 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() && 2313 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() && 2314 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() && 2315 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) ) 2316 { 2317 pNewUpper = pNewNextUpper; 2318 } 2319 } 2320 // <-- 2321 } 2322 else 2323 { 2324 const SwFrm *pCol = rThis.FindColFrm(); 2325 sal_Bool bGoOn = sal_True; 2326 sal_Bool bJump = sal_False; 2327 do 2328 { 2329 if ( pCol->GetPrev() ) 2330 pCol = pCol->GetPrev(); 2331 else 2332 { 2333 bGoOn = sal_False; 2334 pCol = rThis.GetLeaf( MAKEPAGE_NONE, sal_False ); 2335 } 2336 if ( pCol ) 2337 { 2338 // ColumnFrms jetzt mit BodyFrm 2339 SwLayoutFrm* pColBody = pCol->IsColumnFrm() ? 2340 (SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower() : 2341 (SwLayoutFrm*)pCol; 2342 if ( pColBody->ContainsCntnt() ) 2343 { 2344 bGoOn = sal_False; // Hier gibt's Inhalt, wir akzeptieren diese 2345 // nur, wenn GetLeaf() das MoveBwdJump-Flag gesetzt hat. 2346 if( SwFlowFrm::IsMoveBwdJump() ) 2347 { 2348 pNewUpper = pColBody; 2349 // --> OD 2006-05-08 #i53139# 2350 // Now <pNewUpper> is a previous layout frame, which 2351 // contains content. But the new upper layout frame 2352 // has to be the next one. 2353 // --> OD 2006-05-17 #136024# - correct fix for i53139 2354 // Check for wrong page description before using next new upper. 2355 // --> OD 2006-06-06 #i66051# - further correction of fix for i53139 2356 // Check for correct type of new next upper layout frame 2357 // --> OD 2006-07-05 #136538# - another correction of fix for i53139 2358 // Beside type check, check also, if proposed new next upper 2359 // frame is inside the same frame types. 2360 // --> OD 2006-11-02 #i71065# 2361 // Check that the proposed new next upper layout 2362 // frame isn't the current one. 2363 SwLayoutFrm* pNewNextUpper = pNewUpper->GetLeaf( MAKEPAGE_NONE, sal_True ); 2364 if ( pNewNextUpper && 2365 pNewNextUpper != rThis.GetUpper() && 2366 pNewNextUpper->GetType() == pNewUpper->GetType() && 2367 pNewNextUpper->IsInDocBody() == pNewUpper->IsInDocBody() && 2368 pNewNextUpper->IsInFtn() == pNewUpper->IsInFtn() && 2369 pNewNextUpper->IsInTab() == pNewUpper->IsInTab() && 2370 pNewNextUpper->IsInSct() == pNewUpper->IsInSct() && 2371 !rThis.WrongPageDesc( pNewNextUpper->FindPageFrm() ) ) 2372 { 2373 pNewUpper = pNewNextUpper; 2374 } 2375 // <-- 2376 } 2377 } 2378 else 2379 { 2380 if( pNewUpper ) // Wir hatten schon eine leere Spalte, haben 2381 bJump = sal_True; // also eine uebersprungen 2382 pNewUpper = pColBody; // Diese leere Spalte kommt in Frage, 2383 // trotzdem weitersuchen 2384 } 2385 } 2386 } while( bGoOn ); 2387 if( bJump ) 2388 SwFlowFrm::SetMoveBwdJump( sal_True ); 2389 } 2390 } 2391 else //Keine Breaks also kann ich zurueckfliessen 2392 pNewUpper = rThis.GetLeaf( MAKEPAGE_NONE, sal_False ); 2393 2394 // --> OD 2004-06-23 #i27801# - no move backward of 'master' text frame, 2395 // if - due to its object positioning - it isn't allowed to be on the new page frame 2396 // --> OD 2005-03-07 #i44049# - add another condition for not moving backward: 2397 // If one of its objects has restarted the layout process, moving backward 2398 // isn't sensible either. 2399 // --> OD 2005-04-19 #i47697# - refine condition made for issue i44049: 2400 // - allow move backward as long as the anchored object is only temporarily 2401 // positions considering its wrapping style. 2402 if ( pNewUpper && 2403 rThis.IsTxtFrm() && !IsFollow() ) 2404 { 2405 sal_uInt32 nToPageNum( 0L ); 2406 const bool bMoveFwdByObjPos = SwLayouter::FrmMovedFwdByObjPos( 2407 *(pOldPage->GetFmt()->GetDoc()), 2408 static_cast<SwTxtFrm&>(rThis), 2409 nToPageNum ); 2410 if ( bMoveFwdByObjPos && 2411 pNewUpper->FindPageFrm()->GetPhyPageNum() < nToPageNum ) 2412 { 2413 pNewUpper = 0; 2414 } 2415 // --> OD 2005-03-07 #i44049# - check, if one of its anchored objects 2416 // has restarted the layout process. 2417 else if ( rThis.GetDrawObjs() ) 2418 { 2419 sal_uInt32 i = 0; 2420 for ( ; i < rThis.GetDrawObjs()->Count(); ++i ) 2421 { 2422 SwAnchoredObject* pAnchoredObj = (*rThis.GetDrawObjs())[i]; 2423 // --> OD 2005-04-19 #i47697# - refine condition - see above 2424 if ( pAnchoredObj->RestartLayoutProcess() && 2425 !pAnchoredObj->IsTmpConsiderWrapInfluence() ) 2426 // <-- 2427 { 2428 pNewUpper = 0; 2429 break; 2430 } 2431 } 2432 } 2433 // <-- 2434 } 2435 // <-- 2436 2437 //Fuer Follows ist das zurueckfliessen nur dann erlaubt wenn in der 2438 //neuen Umgebung kein Nachbar existiert (denn dieses waere der Master). 2439 //(6677)Wenn allerdings leere Blaetter uebersprungen wurden wird doch gemoved. 2440 if ( pNewUpper && IsFollow() && pNewUpper->Lower() ) 2441 { 2442 // --> OD 2007-09-05 #i79774#, #b6596954# 2443 // neglect empty sections in proposed new upper frame 2444 bool bProposedNewUpperContainsOnlyEmptySections( true ); 2445 { 2446 const SwFrm* pLower( pNewUpper->Lower() ); 2447 while ( pLower ) 2448 { 2449 if ( pLower->IsSctFrm() && 2450 !dynamic_cast<const SwSectionFrm*>(pLower)->GetSection() ) 2451 { 2452 pLower = pLower->GetNext(); 2453 continue; 2454 } 2455 else 2456 { 2457 bProposedNewUpperContainsOnlyEmptySections = false; 2458 break; 2459 } 2460 } 2461 } 2462 if ( !bProposedNewUpperContainsOnlyEmptySections ) 2463 { 2464 if ( SwFlowFrm::IsMoveBwdJump() ) 2465 { 2466 //Nicht hinter den Master sondern in das naechstfolgende leere 2467 //Blatt moven. 2468 SwFrm *pFrm = pNewUpper->Lower(); 2469 while ( pFrm->GetNext() ) 2470 pFrm = pFrm->GetNext(); 2471 pNewUpper = pFrm->GetLeaf( MAKEPAGE_INSERT, sal_True ); 2472 if( pNewUpper == rThis.GetUpper() ) //Landen wir wieder an der gleichen Stelle? 2473 pNewUpper = NULL; //dann eruebrigt sich das Moven 2474 } 2475 else 2476 pNewUpper = 0; 2477 } 2478 // <-- 2479 } 2480 if ( pNewUpper && !ShouldBwdMoved( pNewUpper, sal_True, rbReformat ) ) 2481 { 2482 if( !pNewUpper->Lower() ) 2483 { 2484 if( pNewUpper->IsFtnContFrm() ) 2485 { 2486 pNewUpper->Cut(); 2487 delete pNewUpper; 2488 } 2489 else 2490 { 2491 SwSectionFrm* pSectFrm = pNewUpper->FindSctFrm(); 2492 // --> OD 2006-01-04 #126020# - adjust check for empty section 2493 // --> OD 2006-02-01 #130797# - correct fix #126020# 2494 if ( pSectFrm && !pSectFrm->IsColLocked() && 2495 !pSectFrm->ContainsCntnt() && !pSectFrm->ContainsAny( true ) ) 2496 // <-- 2497 { 2498 pSectFrm->DelEmpty( sal_True ); 2499 delete pSectFrm; 2500 rThis.bValidPos = sal_True; 2501 } 2502 } 2503 } 2504 pNewUpper = 0; 2505 } 2506 2507 // OD 2004-05-26 #i21478# - don't move backward, if flow frame wants to 2508 // keep with next frame and next frame is locked. 2509 // --> OD 2004-12-08 #i38232# - If next frame is a table, do *not* check, 2510 // if it's locked. 2511 if ( pNewUpper && !IsFollow() && 2512 rThis.GetAttrSet()->GetKeep().GetValue() && rThis.GetIndNext() ) 2513 { 2514 SwFrm* pIndNext = rThis.GetIndNext(); 2515 // --> OD 2004-12-08 #i38232# 2516 if ( !pIndNext->IsTabFrm() ) 2517 { 2518 // get first content of section, while empty sections are skipped 2519 while ( pIndNext && pIndNext->IsSctFrm() ) 2520 { 2521 if( static_cast<SwSectionFrm*>(pIndNext)->GetSection() ) 2522 { 2523 SwFrm* pTmp = static_cast<SwSectionFrm*>(pIndNext)->ContainsAny(); 2524 if ( pTmp ) 2525 { 2526 pIndNext = pTmp; 2527 break; 2528 } 2529 } 2530 pIndNext = pIndNext->GetIndNext(); 2531 } 2532 ASSERT( !pIndNext || pIndNext->ISA(SwTxtFrm), 2533 "<SwFlowFrm::MovedBwd(..)> - incorrect next found." ); 2534 if ( pIndNext && pIndNext->IsFlowFrm() && 2535 SwFlowFrm::CastFlowFrm(pIndNext)->IsJoinLocked() ) 2536 { 2537 pNewUpper = 0L; 2538 } 2539 } 2540 // <-- 2541 } 2542 2543 // --> OD 2006-05-10 #i65250# 2544 // layout loop control for flowing content again and again moving 2545 // backward under the same layout condition. 2546 if ( pNewUpper && !IsFollow() && 2547 pNewUpper != rThis.GetUpper() && 2548 SwLayouter::MoveBwdSuppressed( *(pOldPage->GetFmt()->GetDoc()), 2549 *this, *pNewUpper ) ) 2550 { 2551 SwLayoutFrm* pNextNewUpper = pNewUpper->GetLeaf( 2552 ( !rThis.IsSctFrm() && rThis.IsInSct() ) 2553 ? MAKEPAGE_NOSECTION 2554 : MAKEPAGE_NONE, 2555 sal_True ); 2556 // --> OD 2007-01-10 #i73194# - make code robust 2557 ASSERT( pNextNewUpper, "<SwFlowFrm::MoveBwd(..)> - missing next new upper" ); 2558 if ( pNextNewUpper && 2559 ( pNextNewUpper == rThis.GetUpper() || 2560 pNextNewUpper->GetType() != rThis.GetUpper()->GetType() ) ) 2561 // <-- 2562 { 2563 pNewUpper = 0L; 2564 #if OSL_DEBUG_LEVEL > 1 2565 ASSERT( false, 2566 "<SwFlowFrm::MoveBwd(..)> - layout loop control for layout action <Move Backward> applied!" ); 2567 #endif 2568 } 2569 } 2570 // <-- 2571 2572 ASSERT( pNewUpper != rThis.GetUpper(), 2573 "<SwFlowFrm::MoveBwd(..)> - moving backward to the current upper frame!? -> Please inform OD." ); 2574 if ( pNewUpper ) 2575 { 2576 PROTOCOL_ENTER( &rThis, PROT_MOVE_BWD, 0, 0 ); 2577 if ( pNewUpper->IsFtnContFrm() ) 2578 { 2579 //Kann sein, dass ich einen Container bekam. 2580 SwFtnFrm *pOld = rThis.FindFtnFrm(); 2581 SwFtnFrm *pNew = new SwFtnFrm( pOld->GetFmt(), pOld, 2582 pOld->GetRef(), pOld->GetAttr() ); 2583 if ( pOld->GetMaster() ) 2584 { 2585 pNew->SetMaster( pOld->GetMaster() ); 2586 pOld->GetMaster()->SetFollow( pNew ); 2587 } 2588 pNew->SetFollow( pOld ); 2589 pOld->SetMaster( pNew ); 2590 pNew->Paste( pNewUpper ); 2591 pNewUpper = pNew; 2592 } 2593 if( pNewUpper->IsFtnFrm() && rThis.IsInSct() ) 2594 { 2595 SwSectionFrm* pSct = rThis.FindSctFrm(); 2596 //Wenn wir in einem Bereich in einer Fussnote stecken, muss im 2597 //neuen Upper ggf. ein SwSectionFrm angelegt werden 2598 if( pSct->IsInFtn() ) 2599 { 2600 SwFrm* pTmp = pNewUpper->Lower(); 2601 if( pTmp ) 2602 { 2603 while( pTmp->GetNext() ) 2604 pTmp = pTmp->GetNext(); 2605 if( !pTmp->IsSctFrm() || 2606 ((SwSectionFrm*)pTmp)->GetFollow() != pSct ) 2607 pTmp = NULL; 2608 } 2609 if( pTmp ) 2610 pNewUpper = (SwSectionFrm*)pTmp; 2611 else 2612 { 2613 pSct = new SwSectionFrm( *pSct, sal_True ); 2614 pSct->Paste( pNewUpper ); 2615 pSct->Init(); 2616 pNewUpper = pSct; 2617 pSct->SimpleFormat(); 2618 } 2619 } 2620 } 2621 sal_Bool bUnlock = sal_False; 2622 sal_Bool bFollow = sal_False; 2623 //Section locken, sonst kann sie bei Fluss des einzigen Cntnt etwa 2624 //von zweiter in die erste Spalte zerstoert werden. 2625 SwSectionFrm* pSect = pNewUpper->FindSctFrm(); 2626 if( pSect ) 2627 { 2628 bUnlock = !pSect->IsColLocked(); 2629 pSect->ColLock(); 2630 bFollow = pSect->HasFollow(); 2631 } 2632 pNewUpper->Calc(); 2633 rThis.Cut(); 2634 // --> OD 2005-02-23 #b6229852# 2635 // optimization: format section, if its size is invalidated and if it's 2636 // the new parent of moved backward frame. 2637 bool bFormatSect( false ); 2638 // <-- 2639 if( bUnlock ) 2640 { 2641 pSect->ColUnlock(); 2642 if( pSect->HasFollow() != bFollow ) 2643 { 2644 pSect->InvalidateSize(); 2645 // --> OD 2005-02-23 #b6229852# - optimization 2646 if ( pSect == pNewUpper ) 2647 bFormatSect = true; 2648 // <-- 2649 } 2650 } 2651 2652 rThis.Paste( pNewUpper ); 2653 // --> OD 2005-02-23 #b6229852# - optimization 2654 if ( bFormatSect ) 2655 pSect->Calc(); 2656 // <-- 2657 2658 SwPageFrm *pNewPage = rThis.FindPageFrm(); 2659 if( pNewPage != pOldPage ) 2660 { 2661 rThis.Prepare( PREP_BOSS_CHGD, (const void*)pOldPage, sal_False ); 2662 ViewShell *pSh = rThis.getRootFrm()->GetCurrShell(); 2663 if ( pSh && !pSh->Imp()->IsUpdateExpFlds() ) 2664 pSh->GetDoc()->SetNewFldLst(true); //Wird von CalcLayout() hinterher eledigt! 2665 2666 pNewPage->InvalidateSpelling(); 2667 pNewPage->InvalidateSmartTags(); // SMARTTAGS 2668 pNewPage->InvalidateAutoCompleteWords(); 2669 pNewPage->InvalidateWordCount(); 2670 2671 // OD 30.10.2002 #97265# - no <CheckPageDesc(..)> in online layout 2672 if ( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ) 2673 { 2674 if ( bCheckPageDescs && pNewPage->GetNext() ) 2675 { 2676 SwPageFrm* pStartPage = bCheckPageDescOfNextPage ? 2677 pNewPage : 2678 (SwPageFrm*)pNewPage->GetNext(); 2679 SwFrm::CheckPageDescs( pStartPage, sal_False); 2680 } 2681 else if ( rThis.GetAttrSet()->GetPageDesc().GetPageDesc() ) 2682 { 2683 //Erste Seite wird etwa durch Ausblenden eines Bereiches leer 2684 SwFrm::CheckPageDescs( (SwPageFrm*)pNewPage, sal_False); 2685 } 2686 } 2687 } 2688 } 2689 return pNewUpper != 0; 2690 } 2691 2692 /************************************************************************* 2693 |* 2694 |* SwFlowFrm::CastFlowFrm 2695 |* 2696 |* Ersterstellung MA 03. May. 95 2697 |* Letzte Aenderung AMA 02. Dec. 97 2698 |* 2699 |*************************************************************************/ 2700 2701 SwFlowFrm *SwFlowFrm::CastFlowFrm( SwFrm *pFrm ) 2702 { 2703 if ( pFrm->IsCntntFrm() ) 2704 return (SwCntntFrm*)pFrm; 2705 if ( pFrm->IsTabFrm() ) 2706 return (SwTabFrm*)pFrm; 2707 if ( pFrm->IsSctFrm() ) 2708 return (SwSectionFrm*)pFrm; 2709 return 0; 2710 } 2711 2712 const SwFlowFrm *SwFlowFrm::CastFlowFrm( const SwFrm *pFrm ) 2713 { 2714 if ( pFrm->IsCntntFrm() ) 2715 return (SwCntntFrm*)pFrm; 2716 if ( pFrm->IsTabFrm() ) 2717 return (SwTabFrm*)pFrm; 2718 if ( pFrm->IsSctFrm() ) 2719 return (SwSectionFrm*)pFrm; 2720 return 0; 2721 } 2722