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